搜索​​​​

清除过滤器
文章
Qiao Peng · 一月 30, 2022

多语言字符集系列文章-- 第二篇 各种技术对字符集使用的声明

各种技术在交换数据的时候,就需要知道对方给的数据使用什么字符集和字符编码,否则很可能就解码错了。这里列举了医疗行业常见的数据交换技术方式和它们对字符集使用的声明方式。 2.1 文件 文件是字符型数据最常见的交换方式,文本编辑工具通常在保存时都会让用户选择保存成什么字符编码。对于不同的字符编码,文件是如何保存的呢? 通常会在文件头使用字节顺序标志(BOM,Byte Order Mark)来标记文件的编码。下表是常见的编码格式对应的BOM,注意ANSI并不需要BOM,我把它列在这里的目的是希望一目了然。 字节 编码格式 00 00 FE FF UTF-32, big-endian FF FE 00 00 UTF-32, little-endian FE FF UTF-16, big-endian FF FE UTF-16, little-endian EF BB BF UTF-8 空 ANSI 例如,汉字的“中”的各种编码如下: 用Windows的写字板软件将这个汉字分别保存成UTF-8、ANSI、Unicode编码,在UltraEdit打开其16进制模式查看,就可以看到如下的输出: 这里ANSI其实保存的是GBK码(使用GBK代码页936),Unicode其实保存的是UTF16编码。试图以ANSI保存文件时,对超出了GBK编码范围的汉字,Windows写字板软件会提示包含Unicode文字,以ANSI保存会丢失数据,如下图: 对于ANSI保存的包含汉字的文件,代码页信息并不在文件里。并不是所有的文本编辑器和文字处理代码都能正确解析这样的文件,因为它们并不知道代码页。这是可能造成文件中文乱码的一个原因。 另外,前面提到通过BOM可以确定文件编码方式,但并不是所有的文件都使用了BOM。因此特定的文本编辑器和文字处理代码对中文都可能产生显示乱码。 2.2 HTTP 对于HTTP消息内容,包括SOAP、RESTful,浏览器/客户端和服务器怎么知道字符编码呢? HTTP头的Content-Type可以通过参数charset指定文字编码。例如: Content-Type: text/html; charset = UTF-8 如果没有正确配置charset,就可能产生乱码。例如网页表单提交的中文数据,服务器没有正确解码从而产生乱码。 不同的Web服务器都可以设置默认的charset,例如Apache可以修改httpd.conf文件,通过配置AddDefaultCharset指定默认字符集编码。 2.3 XML XML文件当然可以使用前面提到的文件编码方式设置,以HTTP传递的XML数据也可以使用HTTP的文字编码设置。同时,XML规范自己也定义了文字编码声明的方式,从而保证通过任何方式传递(例如TCP)的XML都可以被正确解析。 XML定义的编码方式是设置encoding属性,例如: <?xml version="1.0" encoding="UTF-8"?> 注意,JSON并没有声明文字编码的设置。通常JSON数据都是通过HTTP传递的,因此使用HTTP的文字编码设置。 2.4 数据库连接 数据库连接也是造成文字乱码的一个重灾区。客户端从数据库服务器获取数据、向数据库服务器提交数据,怎么知道数据的文字编码呢? 和数据库相关的文字编码有2部分:数据库内码、数据库连接使用的字符编码。 数据库内码: 由于Unicode码历史并不悠久,数据库管理系统的历史远早于Unicode,直到最近这20年,数据库厂商才开始支持Unicode内码。当然,每个厂商的Unicode内码编码也不一样,例如InterSystems的Caché和IRIS是UTF-16格式,而Oracle是UTF-8和UTF-16。因为UTF-8处理效率低,大多数Unicode数据库都使用UTF-16。现在依然能看到不是Unicode内码的老版本数据库。 很多数据库相关的字符编码问题和数据库内码设置有关。例如国内不少的Oracle安装时没设置过字符编码,数据库内码NLS_CHARACTERSET默认为US7ASCII,客户端字符集NLS_LANG默认为AMERICAN_AMERICA.US7ASCII。这并不会造成中文无法保存,因为数据库只是将客户端的数据逐位保存下来,无论什么编码。但这样保存的中文数据只有Oracle自己的客户端能正常显示,其它的客户端可能就按ASCII处理从而造成乱码。因此正确设置数据库的内码很关键。 数据库连接使用的字符编码: ODBC: 直到ODBC 3.5标准(1997年)之前绝大多数的ODBC连接的函数调用和字符串编码都是ANSI(单字节或双字节),所以中文生僻字大多都会处理异常。 ODBC 3.5 规定ODBC驱动管理器要能够透明地处理Unicode和ANSI之间的转换,从而让ANSI和Unicode的数据库客户端都可以正确地向数据库获取和提交数据。 当然,并不是所有的Unicode字符都能转为ANSI码,例如中文“”字,所以ANSI的数据库客户端依然会遇到生僻字乱码。 JDBC: Java对字符串使用UTF-16编码,如果数据库内码也使用UTF-16,那么不会有乱码问题,例如InterSystems IRIS。但很多数据库并非使用UTF-16,这些数据库的JDBC驱动就需要支持UTF-16和数据库内码之间的转换。通常可以通过设置JDBC的连接字符串的特定属性来实现。 例如mysql的连接字符串中指定characterEncoding: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8 其它连接方式: 另外,很多数据库还提供XDBC之外的连接方式,这些连接方式有自己的字符编码逻辑。 2.5 HL7 V2 在医疗行业,HL7 V2是目前最为广泛使用的消息交换标准。它可以通过文件、TCP、HTTP、SOAP 等多种通道交换。因此,HL7 V2消息标准中,也有设置消息字符编码的字段:MSH-18。正确设置该字段有助于不同的系统正确地处理HL7 V2消息里的字符数据。 例如下面的HL7消息在MSH段设置其字符编码为UTF-8: MSH|^~\&||PHLS|||||ORU^R01|||2.5|||AL|||UTF-8| PID||S2345|S2345^^^PHLS^MR|C9876^^^COR^XX~S45008787^^^MA^DL|张^三||19301019|M|||1 Memorial Drive^^剑桥市^MA^02142||||||||063070516 PV1||O|||||ISCGP001^建国^李|||||||EO|||||HSVN00008|||||||||||||||||||||||||20200912090700|20200912090700 ORC||00265-001|0606:H00550R||||^^^202009120910||202009120910|||ISCGP001^建国^李|PHLS||||||||PHLS||||||||LAB OBR||00265-001|0606:H00550R|CBCD^血常规^L|||202009121049|||||||202009120937|Blood|ISCGP001^Moore^James||||||202009121227|||F OBX||NM|WBC^WHITE BLOOD CELL COUNT||6.24|10(9)/L|4.0-10.6||||F|||202009121049 OBX||NM|RBC^RED BLOOD CELL COUNT||4.99|10x12/L|4.5-5.9||||F|||202009121049 OBX||NM|HGB^HEMOGLOBIN||13.6|g/dL|12.0-16.0||||F|||202009121049 OBX||NM|HCT^HEMATOCRIT||41.6|Percent|36.0-46.0||||F|||202009121049 2.6 其它 在上面提到的和字符集相关的乱码之外,有时我们会混淆一些其它的、并非真正乱码的情况。下面这些中文显示的“乱码”,并非乱码: URL编码: 根据RFC 3986,如果URL的路径中有URL的保留字,就需要对URL路径中的保留字使用转义符% 进行转码,也叫做百分号编码。例如ASCII中下面的字符都需要转义: ! # $ & ' ( ) * + , / : ; = ? @ [ ] %21 %23 %24 %26 %27 %28 %29 %2A %2B %2C %2F %3A %3B %3D %3F %40 %5B %5D 对于非ASCII码字符,按其UTF-8编码字节顺序加%转义。例如“https://cn.community.intersystems.com/post/多语言字符集系列文章-第一篇-多语言字符集和相关标准简史”会被转义为: https://cn.community.intersystems.com/post/%E5%A4%9A%E8%AF%AD%E8%A8%80%E5%AD%97%E7%AC%A6%E9%9B%86%E7%B3%BB%E5%88%97%E6%96%87%E7%AB%A0-%E7%AC%AC%E4%B8%80%E7%AF%87-%E5%A4%9A%E8%AF%AD%E8%A8%80%E5%AD%97%E7%AC%A6%E9%9B%86%E5%92%8C%E7%9B%B8%E5%85%B3%E6%A0%87%E5%87%86%E7%AE%80%E5%8F%B2 其中%E5%A4%9A就是“多”字的UTF-8编码E5A49A的3个字节加上%。 在InterSystems技术平台上,可以用$ZCVT("%E5%A4%9A","I","URI")将URL编码翻译为中文字符,或使用$ZCVT("多","O","URI")将汉字进行URL编码。 HTML实体编码(转义): HTML实体编码(HTML Entity Encode)将字符编码为&开头;结尾的字符串,例如"<"编码为"<"。而中文字符就会被按其unicode编码进行转义,例如“广”字的unicode 10进制码为24191,所以它的HTML实体编码是"广"。在InterSystems技术平台上,可以用$ZCVT("广","I","HTML")将其翻译为中文字符。 Base64 编码: 当使用SOAP传递的数据是一个XML字符串或其它应被视为二进制类型的数据时,通常使用Base64对其进行编码,从而不会破坏XML结构解析。所以它也不是乱码。
问题
jingwei lu · 三月 13, 2022

关于Cache高可用架构的选择

现在我们院区也遇到这样一个问题。关于cache的高可用架构现有有两个方案: 1.选择双节点的完全无共享架构的自动转移镜像集群外加一个灾难恢复镜像 2.就像你提问的那种,两台主机先做Rose HA用一套双活存储实现高可用,然后再弄一台服务器做Rose HA的单机镜像(有可能是同步也有可能是异步那种比如灾难恢复镜像) 现在想问问如果单纯考虑切换时候对业务的影响,如果切换的中断时长什么的,用哪个最好啊?第二种方案真有很多单位用么? 希望有大神能替我解答一下,谢谢。 可以参考下历史的帖子。https://community.intersystems.com/post/backup-strategy-%E5%8F%8C%E6%9C%BA%E5%A4%87%E4%BB%BD%E7%AD%96%E7%95%A5 如果是我,会选择方案1,原因:既然 intersystems 提供了完整的 mirror 高可用方案,就没必要再和第三方的方案掺和在一起,凭空增加了问题排错的复杂度。如果真出现了服务中断,这个时候要第一要务是尽快做出正确的决策,以便尽快恢复服务。架构的复杂性会给自己造成很多不必要的麻烦以及决策上的复杂性 (个人建议,仅供参考。) 我们推荐的高可用性方案是Mirror。也就是配置至少主备两个镜像成员+灾备异步镜像成员,可选配置多个异步报表镜像成员以及多个灾备异步镜像成员。 当然同时推荐的是建立健全的外部备机机制,以及使用外部备份进行恢复的演练,手动升级灾备异步镜像成员为主机的演练。 对于大型应用一般使用ECP创建多台应用服务器,进行多用户的负载分配,再将多台应用服务器连接至数据服务器,数据服务器进行高可用性配置。 感谢分享 感谢分享 常见问题系列-系统管理篇-如何进行数据库备份 InterSystems Caché系统高可用与数据库镜像
文章
YuHao Wan · 十一月 5, 2022

Caché实现SM4分组密码算法

### 0. 算法概述 SM4算法是一种分组密码算法。其分组长度为128bit,密钥长度也为128bit。加密算法与密钥扩展算法均采用32轮非线性迭代结构,以字(32位)为单位进行加密运算,每一次迭代运算均为一轮变换函数F。SM4算法加/解密算法的结构相同,只是使用轮密钥相反,其中解密轮密钥是加密轮密钥的逆序。 ### 1. 密钥及轮密钥 密钥长度为128比特,表示为MK=(MK(0),MK(1),MK(2),MK(3)),其中MKi(i=0,1,2,3)为字。 轮密钥表示为(rk(0),rk(1),...,rk(31)),其中rk(i)(i=0,...,31)为32比特字。轮密钥由秘钥生成。 ![密钥及轮密钥](https://gitee.com/wanyuhao/intersystems/raw/master/%E5%9B%BD%E5%AF%86%E7%AE%97%E6%B3%95SM3,SM4/images/SM4-01.png) ### 2. 消息填充分组 首先,将明文转化为字节,由于SM4加密算法按照128个位进行分组,所以很大几率会出现最后一个分组不够128位的情况,需要进行**填充**,填充方式有很多,比如ZeroPadding、PKCS7Padding、PKCS5Padding,不管使用哪种方式,最后每个分组都是128位。每个分组按照**32位**一个字分成四个字。 #### ECB模式与CBC模式 - ECB模式 电子密码本模式,最古老,最简单的模式,将加密的数据分成若干组,每组的大小跟加密密钥相同。不足的部分进行填充。 按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。 优点:简单,有利于并行计算,误差不会被传递。 缺点:不能隐藏明文的模式,可能对明文进行主动攻击。 - CBC模式 密文分组链接模式,也需要进行分组,不足的部分按照**指定的数据**进行填充。 需要一个**初始化向量**,每个分组数据与上一个分组数据加密的结果进行**异或运算**,最后再进行加密。将所有分组加密的结果连接起来就形成了最终的结果。 优点:不容易进行主动攻击,安全性好于ECB。 缺点:不利于并行计算,误差传递,需要初始化向量。 #### 三种填充方式的比较 某些加密算法要求明文需要按一定长度对齐,叫做**块大小**(BlockSize),比如16字节,那么对于一段任意的数据,加密前需要对最后一个块填充到16 字节,解密后需要删除掉填充的数据。 - **ZeroPadding**,数据长度不对齐时使用**0**填充,否则不填充。 - **PKCS7Padding**,假设数据长度需要填充n(n>0)个字节才对齐,那么填充n个字节,每个字节都是**n**;如果数据本身就已经对齐了,则填充一块长度为块大小的数据,每个字节都是块大小。 - **PKCS5Padding**,PKCS7Padding的子集,块大小固定为**8**字节。 由于使用PKCS7Padding/PKCS5Padding填充时,最后一个字节肯定为填充数据的长度,所以在解密后可以准确删除填充的数据,而使用ZeroPadding填充时,没办法区分真实数据与填充数据,所以只适合以\0结尾的字符串加解密。 ### 3. 迭代运算 本加解密算法由32次迭代运算和1次反序变换R组成。 ![迭代运算](https://gitee.com/wanyuhao/intersystems/raw/master/%E5%9B%BD%E5%AF%86%E7%AE%97%E6%B3%95SM3,SM4/images/SM4-02.png) #### 3.1 轮函数F和合成置换T ![轮函数和合成置换T](https://gitee.com/wanyuhao/intersystems/raw/master/%E5%9B%BD%E5%AF%86%E7%AE%97%E6%B3%95SM3,SM4/images/SM4-03.png) ### 4. Caché实现 ``` /// SM4算法是一种分组密码算法。其分组长度为128bit,密钥长度也为128bit。 /// 加密算法与密钥扩展算法均采用32轮非线性迭代结构,以字(32位)为单位进行加密运算,每一次迭代运算均为一轮变换函数F。 /// SM4算法加/解密算法的结构相同,只是使用轮密钥相反,其中解密轮密钥是加密轮密钥的逆序。 /// 本方法适用于 ECB模式,ZeroPadding填充模式 Class Utility.SM4 Extends %RegisteredObject { /// Creator: wyh /// CreatDate: 2022-11-03 /// Description:SM4加密 /// Input: msg:原文 mk:128位密钥 /// Output: 密文 /// Debug: w ##class(Utility.SM4).Encrypt("342622199009262982", "F2D8D966CD3D47788449C19D5EF2081B") ClassMethod Encrypt(msg, mk) { #; 1. 密钥及轮密钥 #; a) 密钥长度为128比特,表示为MK=(MK(0),MK(1),MK(2),MK(3)),其中MKi(i=0,1,2,3)为字 #; b) 轮密钥表示为(rk(0),rk(1),...,rk(31)),其中rk(i)(i=0,...,31)为32比特字。轮密钥由密钥生成。 #; 密钥扩展算法: #; (K(0),K(1),K(2),K(3))=(MK(0)^FK(0),MK(1)^FK(1),MK(2)^FK(2),MK(3)^FK(3)) #; rk(i)=K(i+4)=K(i)^T'(K(i+1)^K(i+2)^K(i+3)^CK(i)),i=0,1,...,31 #; 系统参数FK(0)=(A3B1BAC6),FK(1)=(56AA3350),FK(2)=(677D9197),FK(3)=(B27022DC) #; 固定参数CK(i)(i=0,1,...,31)为: #; 00070E15, 1C232A31, 383F464D, 545B6269, #; 70777E85, 8C939AA1, A8AfB6BD, C4CBD2D9, #; E0E7EEF5, FC030A11, 181F262D, 343B4249, #; 50575E65, 6C737A81, 888F969D, A4ABB2B9, #; C0C7CED5, DCE3EAF1, F8FF060D, 141B2229, #; 30373E45, 4C535A61, 686F767D, 848B9299, #; A0A7AEb5, BCC3CAD1, D8DFE6ED, F4FB0209, #; 10171E25, 2C333A41, 484F565D, 646B7279. s mk = $zcvt(mk, "L") f i = 0 : 1 : 3 d .s MK(i) = $e(mk, 8 * i + 1, 8 * (i + 1)) s FK = "a3b1bac656aa3350677d9197b27022dc" f i = 0 : 1 : 3 d .s FK(i) = $e(FK, 8 * i + 1, 8 * (i + 1)) s CK = "00070e151c232a31383f464d545b626970777e858c939aa1a8afb6bdc4cbd2d9e0e7eef5fc030a11181f262d343b424950575e656c737a81888f969da4abb2b9c0c7ced5dce3eaf1f8ff060d141b222930373e454c535a61686f767d848b9299a0a7aeb5bcc3cad1d8dfe6edf4fb020910171e252c333a41484f565d646b7279" f i = 0 : 1 : 31 d .s CK(i) = $e(CK, 8 * i + 1, 8 * (i + 1)) f i = 0 : 1 : 3 d .s K(i) = ..HexXOR(MK(i), FK(i)) f i = 4 : 1 : 35 d .s K(i) = ..HexXOR(K(i - 4), ..T2(..HexXOR(..HexXOR(..HexXOR(K(i + 1 - 4), K(i + 2 - 4)),K(i + 3 - 4)), CK(i - 4)))) f i = 0 : 1 : 31 d .s rk(i) = K(i + 4) #; 2. 消息填充分组 #; 每组128位,每组再分X(0),X(1),X(2),X(3)作为明文输入. s hex = ..s2hex(msg) s len = $l(hex)/32 s rtn = "" f i = 0 : 1 : len-1 d .k X .s M(i) = $e(hex, 32 * i + 1, 32 * (i + 1)) .f j = 0 : 1 : 3 d ..s X(j) = $e(M(i), 8 * j + 1, 8 * (j + 1)) #; 3. 迭代运算,密文输出(Y(0),Y(1),Y(2),Y(3)) #; a) 32次迭代运算 #; X(i+4)=F(X(i),X(i+1),X(i+2),X(i+3),rk(i)),i=0,1,...,31 #; F(X(i),X(i+1),X(i+2),X(i+3),rk(i))=X(i)^T(X(i+1)^X(i+2)^X(i+3)^rk(i)),i=0,1,...,31 #; b)反序变换 #; (Y(0),Y(1),Y(2),Y(3))=R(X(32),X(33),X(34),X(35))=(X(35),X(34),X(33),X(32)) .f k = 0 : 1 : 31 d ..s X(k + 4) = ..HexXOR(X(k), ..T(..HexXOR(..HexXOR(..HexXOR(X(k + 1), X(k + 2)), X(k + 3)), rk(k)))) .s rtn = rtn_X(35)_X(34)_X(33)_X(32) q rtn } /// Creator: wyh /// CreatDate: 2022-11-03 /// Description:SM4解密 /// 解密变换与加密变换结构相同,不同的仅是轮密钥的使用顺序,解密时使用轮密钥序(rk(31),rk(32),...,rk(0)). /// Input: hex:密文 mk:128位密钥 /// Output: 明文 /// Debug: w ##class(Utility.SM4).Decrypt("5efcbbfdb7a326b340295acb1c0e20fe2622730932bdb5302b5a4ee308944ecc", "F2D8D966CD3D47788449C19D5EF2081B") ClassMethod Decrypt(hex, mk) { s mk = $zcvt(mk, "L") f i = 0 : 1 : 3 d .s MK(i) = $e(mk, 8 * i + 1, 8 * (i + 1)) s FK = "a3b1bac656aa3350677d9197b27022dc" f i = 0 : 1 : 3 d .s FK(i) = $e(FK, 8 * i + 1, 8 * (i + 1)) s CK = "00070e151c232a31383f464d545b626970777e858c939aa1a8afb6bdc4cbd2d9e0e7eef5fc030a11181f262d343b424950575e656c737a81888f969da4abb2b9c0c7ced5dce3eaf1f8ff060d141b222930373e454c535a61686f767d848b9299a0a7aeb5bcc3cad1d8dfe6edf4fb020910171e252c333a41484f565d646b7279" f i = 0 : 1 : 31 d .s CK(i) = $e(CK, 8 * i + 1, 8 * (i + 1)) f i = 0 : 1 : 3 d .s K(i) = ..HexXOR(MK(i), FK(i)) f i = 4 : 1 : 35 d .s K(i) = ..HexXOR(K(i - 4), ..T2(..HexXOR(..HexXOR(..HexXOR(K(i + 1 - 4), K(i + 2 - 4)),K(i + 3 - 4)), CK(i - 4)))) f i = 0 : 1 : 31 d .s rk(i) = K(35 - i) s len = $l(hex)/32 s rtn = "" f i = 0 : 1 : len-1 d .k X .s M(i) = $e(hex, 32 * i + 1, 32 * (i + 1)) .f j = 0 : 1 : 3 d ..s X(j) = $e(M(i), 8 * j + 1, 8 * (j + 1)) .f k = 0 : 1 : 31 d ..s X(k + 4) = ..HexXOR(X(k), ..T(..HexXOR(..HexXOR(..HexXOR(X(k + 1), X(k + 2)), X(k + 3)), rk(k)))) .s rtn = rtn_X(35)_X(34)_X(33)_X(32) q ..hex2str(rtn) } /// 非线性变换τ构成 /// τ由4个并行的S盒,设输入A=(a0,a1,a2,a3),输出为B=(b0,b1,b2,b3) /// (b0,b1,b2,b3)=τ(A)=(Sbox(a0),Sbox(a1),Sbox(a2),Sbox(a3)) /// w ##class(Utility.SM4).tau("942600f0") ClassMethod tau(a) { f i = 0 : 1 : 7 d .s a(i) = $e(a, i + 1) s s(0) = "d690e9fecce13db716b614c228fb2c05" s s(1) = "2b679a762abe04c3aa44132649860699" s s(2) = "9c4250f491ef987a33540b43edcfac62" s s(3) = "e4b31ca9c908e89580df94fa758f3fa6" s s(4) = "4707a7fcf37317ba83593c19e6854fa8" s s(5) = "686b81b27164da8bf8eb0f4b70569d35" s s(6) = "1e240e5e6358d1a225227c3b01217887" s s(7) = "d40046579fd327524c3602e7a0c4c89e" s s(8) = "eabf8ad240c738b5a3f7f2cef96115a1" s s(9) = "e0ae5da49b341a55ad933230f58cb1e3" s s(10) = "1df6e22e8266ca60c02923ab0d534e6f" s s(11) = "d5db3745defd8e2f03ff6a726d6c5b51" s s(12) = "8d1baf92bbddbc7f11d95c411f105ad8" s s(13) = "0ac13188a5cd7bbd2d74d012b8e5b4b0" s s(14) = "8969974a0c96777e65b9f109c56ec684" s s(15) = "18f07dec3adc4d2079ee5f3ed7cb3948" f i = 0 : 1 : 15 d .f j = 0 : 1 : 15 d ..s s(i, j) = $e(s(i), 2 * j + 1, 2 * (j + 1)) s rtn = "" f i = 0 : 1 : 3 d .s r = ..hex2int(a(2 * i)) .s c = ..hex2int(a(2 * i + 1)) .s rtn = rtn _ s(r, c) return rtn } /// 线性变换L /// 非线性变换τ的输出是线性变换L的输入.设输入为B,输出为C. /// C=L(B)=B^(B
文章
Johnny Wang · 十二月 19, 2021

我们和Oracle、AWS、SAP数据库做了开源速度对比测试

如果您经常阅读我们的博客,您可能记得去年夏天我们进行了 InterSystems 速度测试,该测试由 ESG 验证,旨在测试数据库可以同时摄取和查询的数据量,以及这表现出的具体的影响。从那以后,我们 GitHub 页面的许多访问者一直在根据自己的想法重复验证这个测试 最初,第一次数据库速度测试将 InterSystems IRIS 数据平台与来自许多不同云和数据管理供应商的流行数据库进行了比较。令人兴奋的是,我们现在可以宣布,我们已经将数据库性能测试从 SAP HANA、AWS Aurora MySQL、SAP Sybase ASE 和 AWS RDS SQL Server 扩展到包括 PostgreSQL、MariaDB 和 Oracle Enterprise,所有这些都跑在 Amazon Web Services (AWS )上面。 我们为什么要做这一次开源速度测试? 通过模拟不支持任何特定产品的多工作负载用例,速度测试往往充当了另一种数据库性能测试工具,可以根据测试结果来确定哪个数据库或数据平台最适合业务需求来做出决策。随着许多公司继续进行数字化转型并探索传统技术的替代品,这种能力被证明是至关重要的。 数据库速度测试最大的特点就是您可以轻松地在云端或您的机器上自己体验它,并且由于我们已将测试作为可定制的开源代码发布,它可以扩展到您自己的数据和查询。 许多人将其视为微服务的首选平台,开源速度测试现在也可在 Kubernetes 上运行,以响应该应用程序在 InterSystems 开发人员社区中越来越受欢迎的现状。这意味着除了能够使用 AWS 和 Amazon Elastic Kubernetes Service (EKS) 之外,开发人员还可以了解 InterSystems IRIS 如何在 Kubernetes 集群上执行并利用 InterSystems Kubernetes Operator。 InterSystems IRIS 如何与竞争对手抗衡? 数据库速度测试着眼于同步摄取和查询性能的特定用例,这是医疗、金融、供应链和制造等许多行业实时用例的基本要求。 最新速度测试的结果发现,与 AWS MariaDB 相比,InterSystems IRIS 在测试期间摄取的记录多 620.9%,到最后摄取它们的速度提高了 717.3%。将 InterSystems IRIS 与在公共云上运行的 Sybase ASE 的性能进行比较发现,InterSystems IRIS 在测试期间摄取的记录多 4862.8%,在测试结束时摄取记录的速度提高了 6733.4%。 对于任何希望对其基础架构进行现代化改造以提高实时和接近实时的数据库性能的公司,这些指标都极为重要。此外,对于那些在 SAP Sybase ASE 上运行生产应用程序的公司,InterSystems 对 Transact-SQL 的本机支持允许这些应用程序的无缝迁移,通常不需要重写自定义代码。 不要只相信我们的话,请访问我们的 GitHub 页面,亲自对 InterSystems IRIS 进行测试,或在此处了解有关速度测试如何工作的更多信息。 阅读更多关于 Amir Samary 的 InterSystems IRIS 数据平台速度测试的博客文章 阅读更多关于去年夏天我们进行的 InterSystems 速度测试 关于作者:Amir Samary Amir Samary 已在数据库、互操作性和 InterSystems 技术方面工作了 20 多年。 Amir 致力于为使用 InterSystems 技术为阿根廷、巴西、智利、哥伦比亚、乌拉圭和美国的各个行业构建解决方案的合作伙伴、客户和开发人员提供支持。 这使 Amir 能够理解和试验不同技术、文化和基础设施现实中的模式和架构。 Amir Samary 目前担任解决方案架构经理,他领导 InterSystems 的一组解决方案开发人员。 他主修计算机科学,辅修数学。 查看原文 阅读更多关于 Amir Samary 的 InterSystems IRIS 数据平台速度测试的博客文章 阅读更多关于去年夏天我们进行的 InterSystems 速度测试 这两个还有文中的其他链接可以换成中文链接(如果有)吗?谢谢! 关于:阅读更多关于去年夏天我们进行的 InterSystems 速度测试,请查看链接:https://cn.community.intersystems.com/post/%E6%B4%9E%E5%AF%9F%E6%96%B0%E7%9A%84-intersystems-%E9%80%9F%E5%BA%A6%E6%B5%8B%E8%AF%95 谢谢! 直接在原文里改吧
文章
Hao Ma · 一月 4, 2023

IRIS, Caché监控指导 - 介绍

本文章是一个系列,主要目的是介绍给IRIS,Caché的终端用户如何方便的监控您的系统。 InterSystems系统的监控很难吗?需要学习很多技术吗? 我的答案是还好。 关于Caché和IRIS监控,无论是那部分内容,在InterSystems的在线文档或者开发者论坛,其实都能找到相关的说明和方案。但问题是太多,太杂乱,没有一个“操作维护手册”的东西。结果是,如果您是一个新手的InterSystems产品的维护工程师或者管理员,您要花很多的时间在大量的文档里找答案。 还有一个问题是文档中很多章节的内容又太深,包含了一些开发人员才关心的内容,这是Caché或者IRIS的特性造成的,因为它首先是一个开发平台。结果是,对于管理员,很多文档的很不友好。 因此,我要写的这个文章的的目的是这样的: - 简单。只介绍管理维护人员需要的内容。只介绍和监控相关的内容。其他比如备份恢复,扩容,修改配置等等基本不涉及。 - 易学。文章的期待读者是系统管理员,因此不需要您有编程能力或者InterSystems编程语言的基础。我系统对您的每个日常工作和关注的主题,给出最容易实现的操作步骤。 - 对读者的要求低,您只需要了解基本的Caché操作,包括 - Caché的用户维护界面 - 操作终端(Terminal)的操作 - 基本的Caché命令的格式 让我们进入主题。有几个要点要先交代一下。 ### InterSystems产品的几个使用的场景 也就是谁在用什么产品 - 场景一:东华的iMedical用户 iMedical 8.5之前的版本使用Caché。 2022年版本8.5发布并开始部署,它的底层是InterSystems IRIS。 - 场景二:独立的InterSystems IRIS实例或者InterSystems HealthShare InterSystems HealthShare是在IRIS平台上面构建的数据共享平台,用于多个医疗机构之间的数据共享,通常会由多个InterSystems IRIS实例组成。本文并不介绍HealthShare的具体技术,您如果是HealthShare的用户,可以通过本文了解单一的IRIS实例的监控。 - 场景三: 医院的集成平台Ensemble用户 从监控维护的角度讲,Ensemble和Health Connect对于医院用户其实是一个东西。Health Connect是最近一些年InterSystems公司对医疗行业使用的Ensemble的一个产品名称。在后面的文章里, 我会只用Ensemble这个名字。 ### 什么是系统监控 简单说,监控工作基本就两块: 1. 监控告警和日志 简单的说,当系统有需要管理员关注的事件发生时,管理员可以及时得到通知。关注的事件通常包括底层的告警,比如CPU占用或者数据库组件出错,或者上层应用的事件,比如一个消息队列太长了。 2. 指标的测量 如果要监控的系统本身有完美的日志和告警通知,那么指标的检测就不那么重要。但实际场景中,用户不仅要检测客户化的上层应用指标,也希望看到底层的指标值,哪怕仅仅是为了展示。 这时候,就需要一个好的指标测量的方案。这里“好的方案”的意思是稳定,易于维护,容易客户定制化的修改。 ### 本文章的组织和您可能感兴趣的内容 如果您是新手,请让我先来强调一下IRIS, Caché和Ensemble的区别 - IRIS, Cache'是开发平台,而不仅仅是数据库。 ​ 举例来说,iMedical的生产环境有很多“应用服务器”,它们是一个个单独部署的Caché实例。它们并不存数据,而仅仅是应用。因此对Caché应用服务器的监控肯定是和数据服务器是不一样的。 - Ensemble是一个应用 Ensemble是在Caché平台上的开发出的消息引擎框架(framework)。它内置了很多用于消息分发传递的组件,用于搭建一个消息引擎。如果只用内置的组件,那么Ensemble几乎可以被看成一个应用。但现实实施中,程序员会使用已有的组件,适配器等开发定制化的组件,这时候Ensemble就是一个开发框架。 无论如何,Ensemble是工作在Cache'或者IRIS之上的,所以Ensemble的维护人员一定要先学维护Cache'或者IRIS。 综上所述, InterSystems产品的监控包括 - IRIS或者Caché的监控(适用于上面所有3个场景的维护人员),包括的内容 - [IRIS,Caché健康检查](./IRIS和Caché健康检查建议.md) - [IRIS,Caché的日志和错误]() - [指标(metrics)的监控] - 数据库性能的监控(适用于场景一,场景二的维护人员) - SQL性能的监控 - 索引的使用情况的监控 - Ensemble的监控(适用于上面场景三的维护人员), 包括 - Ensemble的日志和错误]() - Ensemble的消息统计 除了最基本的监控有关的工作,文章内容里还会包括最基本的和系统健康检查,提交测试报告的内容。也会介绍一些工具,比如SNMP, InterSystems SAM等等。我在工作中了解的一些用户的好的方案,实现等等, 也会和各位分享。 请看下一篇 [IRIS, Caché监控指导(1)-健康检查](https://cn.community.intersystems.com/post/iris-cach%C3%A9%E7%9B%91%E6%8E%A7%E6%8C%87%E5%AF%BC-%E7%B3%BB%E7%BB%9F%E5%81%A5%E5%BA%B7%E6%A3%80%E6%9F%A5)
文章
Nicky Zhu · 五月 20, 2021

互操作消息统一管理系列:MessageBank

## 一. 企业信息库简介 企业信息库(MessageBank)是一个可选的远程归档设施,可以从多个来自不同实例的互操作性Production中收集信息、事件日志项目和搜索表项。如下图所示: ![image](/sites/default/files/inline/images/1_1_0.png) 这套环境由两种角色的实例构成: 企业信息库服务器,它本身也是一个Production,完全由Message Bank服务组成,接收来自任何数量的客户Production提交的消息、日志等。 客户端Operation(Message Bank Operation),将其添加到一个正在运行的Production中,并用企业信息库服务器的地址进行配置。如连接通畅,消息和日志即可自动转发到Message Bank并在其中存储。 为了使你能方便地看到信息库中的信息,InterSystems IRIS®提供了以下附加选项。 对于企业信息库实例,管理门户自动包括企业监控器页面,在那里你可以监控客户端Production的状态,浏览消息库,并对被监控客户的消息进行检索。 对于每个客户端实例,你在消息库实例中配置一个到企业监控器的链接。 如下所示: ![image](/sites/default/files/inline/images/1_2_0.png) ## 二. 常见应用场景 ### 消息归档 在使用IRIS互操作性时,对于生产环境,为保障其有充足的磁盘空间和即时查询的效率,通常会采用消息和日志过期策略。在生产环境中只保留近期(如一个月)的信息以备回溯,过期数据将定期被清除。因此,如果有长期保留消息(如在生产环境清除周期之外还需要更长时间的回溯)的需求,则可以通过Message Bank对消息和日志进行长期保存。 ### 企业消息仓库 对于集成规模较大,集成业务较多的大型企业和集团(如大型医院、医联体、医共体),往往会采用多套互操作性实例支撑数据交换和集成业务。在这种环境下,可以通过Message Bank汇聚和存储整个企业环境下的所有互操作消息和日志,为业务集中监控、跨实例业务故障分析等工作创造条件。 ### 消息和日志再利用 理想条件下,实施互操作性项目之后,消息和日志中就会包括大量的业务数据,典型的包括下达的医嘱、患者信息、医疗记录等。通过对Message Bank中的数据进行分析和挖掘,能够获得有价值的业务信息。 接下来我们会为大家介绍Message Bank的搭建过程。 ## 三. 搭建Message Bank ### 创建Message Bank 命名空间 在生产所用的实例之外,我们需要使用一台独立的实例用于安装和配置Message Bank(实例安装过程和License激活过程从略,请查看安装文档或联系您的支持工程师)。 在该实例上,创建一个命名空间安装Message Bank,如下所示: ![image](/sites/default/files/inline/images/1_3_0.png) 由于Message Bank本质上由Production实现,因此创建命名空间时要选上对互操作Producation的支持。 InterSystems为大家提供了可以套用的Production模版。因此,请按照以下步骤创建Production: 在刚才创建的命名空间MessageStore下创建类MessageBank.BankProduction,继承Ens.Enterprise.MsgBank.Production并将Ens.Enterprise.MsgBank.Production中的XData代码块拷贝到新建的类中,如下所示: ![image](/sites/default/files/inline/images/1_4_0.png) 保存和编译该类,并在Interoperability菜单中加载该Production。 ![image](/sites/default/files/inline/images/1_5_0.png) 其中已部署了两个服务: MsgBankService:该服务通过TCP连接从其他Production接收消息 注意该Service默认使用9192端口与其他客户端通信。 ![image](/sites/default/files/inline/images/1_6_0.png) MonitorService:该服务收集其他实例的其他Production的运行状态 此时,这个Production已经具备了从其他实例的Production收集消息和事件信息的能力,可直接启动。当然,我们还需要配置与客户端的连接。 ### 为客户端Production添加消息转发Operation 假设我们已经有一个可运行的的如下所示的Production ![image](/sites/default/files/inline/images/1_7_0.png) 注意这个Production与Message Bank不在同一个实例上。 ![image](/sites/default/files/inline/images/1_8_0.png) 这个Production接收XML格式的报文并根据报文类型转发到不同的BO。 要将这个Production加入Message Bank,则需要对该客户端Production添加Business Operation Ens.Enterprise.MsgBankOperation。 ![image](/sites/default/files/inline/images/1_9_0.png) 对于该Operation,需要指定要连接的Message Bank的IP地址和端口。 ![image](/sites/default/files/inline/images/1_10_0.png) 同时,建议开启这个Operation的“启用存档”开关,保证在Message Bank临时故障时挂起消息,在故障恢复后还能捕捉到故障期间的消息和日志。 配置完成后启用该Operation。 ### 在Message Bank中加入客户端信息 上述连接建立后,客户端和Message Bank间的连接已建立,还需要配置Message Bank和客户端Production之间的程序信息(相当于注册)才能正常工作。 #### 添加客户端连接凭据 ![image](/sites/default/files/inline/images/1_11_0.png) Message Bank需要通过Web请求访问客户端信息,因此,需要配置客户端凭据,即可通过管理门户访问客户端Production的用户名和密码(对访问权限的设计和配置,可参见我们之前的文章:IRIS中的权限管理) #### 在Message Bank上配置客户端信息 在Message Bank中的Interoperability菜单中找到“企业系统”项 ![image](/sites/default/files/inline/images/1_12_0.png) 在操作页面上通过“新建连接” ![image](/sites/default/files/inline/images/1_13_0.png) 新建连接添加客户端信息。 ![image](/sites/default/files/inline/images/1_14_0.png) 注意其中的服务Web应用路径为该客户端实例上Production所在的命名空间的Web Application根路径,并引用之前填写的凭据。 如配置正确,可通过企业监视器查看连接状态 ![image](/sites/default/files/inline/images/1_15_0.png) 连接成功的状态如下: ![image](/sites/default/files/inline/images/1_16_0.png) #### 在客户端上添加Message Bank连接信息(可选步骤) 如果需要在客户端上通过链接查看消息仓库的信息,则可以配置链接。 在客户端上,在被采集的Production所在的命名空间的Interoerability菜单中“消息仓库链接”配置 ![image](/sites/default/files/inline/images/1_17_0.png) 输入Message Bank所在的IP、端口和Production所在的命名空间,保存并“开始”即可跳转到Messsage Bank的企业监视器。 ![image](/sites/default/files/inline/images/1_18_0.png) 需要注意的是,该配置固定采用了/csp/[namespace]为Message Bank的Web Application路径,而在Message Bank实例上,这个Web Application默认的路径是/csp/healthshare/messagestorage。可通过在Message Bank上添加一个Web Application,拷贝/csp/healthshare/messagestorage的配置。 ![image](/sites/default/files/inline/images/1_19_0.png) ## 四. Message Bank的实施效果 ### 测试消息 在客户端的Production中触发任意流程产生消息,如下所示: ![image](/sites/default/files/inline/images/1_20_0.png) 此时通过Message Bank中的“消息仓库查看器”即可查询存储在消息仓库中的消息 ![image](/sites/default/files/inline/images/1_21_0.png) 如下: ![image](/sites/default/files/inline/images/1_22_0.png) 可以注意到该消息已被同步到消息仓库。 需要注意,使用“消息仓库查看器”时,查询的是在Message Bank中存储的消息数据,使用在Message Bank上定义的Search Table或索引进行查询;如果通过“企业消息查看器”查询,则是链接到客户端的消息查看器查询,应用的是在客户端上定义的索引。 ### 消息的存储 根据在源系统的消息类型的不同,传递到Message Bank后会以不同的形式保存消息。 #### 虚拟文档 对于HL7 V2等标准消息或基于XML虚拟文档的消息,在Message Bank这一侧也同样以虚拟文档的形式保存。 ![image](/sites/default/files/inline/images/1_23_0.png) 特别注意其中的如下属性: MessageBodyClassName:该类型为消息在Message Bank侧持久化的类型。 ClientBodyClassName:该类型为消息在客户端侧持久化的类型。 在本例中可以看到,客户端通过EnsLib.EDI.XML.Document类型传递的消息,在Message Bank中也是通过EnsLib.EDI.XML.Document保存。 MessageBodyId:消息在Message Bank中的物理主键 ClientBodyId:客户端侧持久化消息的物理主键 ClientSessionId:客户端会话Id #### 结构化消息 对于基于Ens.Request等持久化类型的消息,在Message Bank这一侧则默认使用字符流来保存。 例如,对于如下的客户端结构化消息传输 ![image](/sites/default/files/inline/images/1_24_0.png) 在Message Bank中的保存形式为: ![image](/sites/default/files/inline/images/1_25_0.png) 可见: MessageBodyClassName:消息在Message Bank中以%Stream.GlobalCharacter即字符流进行保存 因此,无论是保存为EnsLib.EDI.XML.Document或是%Stream.GlobalCharacter,在Message Bank中保存的消息本身都缺乏足够的结构化特征和索引以支持对消息体的检索,我们会在下一篇教程《[互操作消息统一管理系列:SearchTable加速检索](https://cn.community.intersystems.com/post/%E4%BA%92%E6%93%8D%E4%BD%9C%E6%B6%88%E6%81%AF%E7%BB%9F%E4%B8%80%E7%AE%A1%E7%90%86%E7%B3%BB%E5%88%97%EF%BC%9Asearchtable%E5%8A%A0%E9%80%9F%E6%A3%80%E7%B4%A2)》中介绍如何通过构建Search Table来检索这些消息。 对于Message Bank相关的内容,可参见: https://docs.intersystems.com/healthconnect20201/csp/docbook/DocBook.UI.Page.cls?KEY=EGDV_message_bank 也欢迎与我们联系获得更详细的信息。
文章
Hao Ma · 五月 26, 2023

IRIS镜像配置(4)_配置后的步骤

题外话:我刚刚翻译了InterSystems专家Bob Binstock的[Caché Mirroring 101:简要指南和常见问题解答](https://cn.community.intersystems.com/post/cach%C3%A9-mirroring-101%EF%BC%9A%E7%AE%80%E8%A6%81%E6%8C%87%E5%8D%97%E5%92%8C%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E8%A7%A3%E7%AD%94)。 尽管题目是Caché Mirror 101, 而且是写于2016年,但因为讲解的都是Mirror的基本原理,所以在大量使用IRIS的今天也完全适用。 前面的3篇文章,包括了配置Mirror的各个方面。如果您照着操作,现在已经有了一个工作的mirror环境,并加入了您的数据库。然而,还没完,这篇我来讨论一下后面的工作,首先的问题是: **Mirror不复制什么** 简单说,Caché/IRIS镜像是**数据库复制(Database Replication)**。在Caché/IRIS里什么是数据库?也就是**Cache.dat和iris.dat**文件。数据库的修改日志,也就是journal,从主机被传送到其他镜像成员。而除此之外的内容,需要维护人员来分别的个个处理, 解决这些内容在各个镜像成员间的拷贝。需要很多的计划和细心。 >系统数据库, 包括IRISSYS, IRISTEMP, IRISLIB等等, 这些Caché/IRIS本身的数据库不应该被加入Mirror,在大多数Caché/IRIS版本里也都设置成不可以加入入MIRROR。 > >例外的HealthCare产品, HSSYS需要做Mirror, HSCustom可以做Mirror, 而HSLIB不可以Mirror 我们可以把问题转换成下面的题目: ## 需要人工在镜像成员中同步的项目 ### 命名空间(namespace)和Mapping 命名空间是应用开发的概念,它使用数据库。命名空间定义了3种映射关系:Package Mapping, Routing Mapping, Global Mapping。这样在一个命名空间可以使用多个数据库的内容。 通常情况下,用户会在主机创建命名空间的同时,创建一个新的带有mirror属性的数据库,然后会在其他mirror成员中手工一个个的创建命名空间,加入镜像的数据库。之后,管理员无需考虑更多的操作。 然而,对命名空间的修改,比如要添加或者删除命名空间的某些mapping,这偶尔会需要,尤其是应用迭代和系统扩容的情况下,那么,管理员/实施人员,必须清楚Mirror无法同步这个修改,您必须手工同步修改到其他机器去。 如果配置的mapping比较多, 我建议使用Manifest来操作。Mainfest是一个xml的文本,用来安装或者修改Caché/IRIS的配置,你可以参考[在线文档: Using a Manifest](https://docs.intersystems.com/iris20231/csp/docbook/DocBook.UI.Page.cls?KEY=GCI_manifest), 或者社区文章[使用Manifest](https://cn.community.intersystems.com/post/%E4%BD%BF%E7%94%A8manifest)。 这里给一个配置mapping的例子: ```xml ``` 如果是资深的Caché维护工程师,懂得如果修改CPF文件并在不重启实例的情况下应用修改后的内容,可以考虑把主机上的CPF中的mapping部分复制粘贴到其他机器。如果您没有这方面的经验,我不建议这种方式。 另外,在IRIS 2022后的版本中有了一个新工具,Configuration Merge。 文档在[这里](https://docs.intersystems.com/iris20231/csp/docbook/Doc.View.cls?KEY=ACMF)。可惜只有最新版的IRIS或者Health Connect 用户有的用。 ### 数据库的修改 数据库的内容会通过Journal从主机同步到其他成员,但修改不会,一般会遇到的是**压缩和截断**。 由于某种错误操作,某个数据库,会扩展到不正常的大,而当错误修正后,用户可能需要对该数据库进行压缩和截断,以释放被错误占用的空闲的磁盘空间。 由于除主机外,其他镜像成员的数据库都是只读的,这个操作的顺序应该是这样: 1. 在主机A执行压缩和截断 2. 切换到备机B, 再次执行压缩和截断。 3. 异步成员DR。 一种方案是吧DR提升到备机。这时当前的备机A会将为灾备,然后再切换DR为主机,再进行压缩和截断。 还有一个选择,就是重新配置DR上的这个数据库,这需要从主机到DR的数据库备份和恢复。 ### IRIS实例的配置 从最常用的内存的配置,Service的配置, **用户,权限,资源**的配置等等。它们都不会被MIRROR同步。如果您在MIRROR主机里做了修改了缩表的大小,或者启动了一个,比如TELNET服务, 您需要人工在其他机器上做相同操作。 像上面的mapping配置一样,这里还是建议使用Manifest人工同步IRIS得修改。注意的是,Mainfest不保证能支持所有的配置。比如在Caché的版本下, 比如您在主机上启动了TELNET服务, Manifest没有相应的标签。这种情况下, 如果您熟悉ObjectScript语言,可以把ObjectScript实现加入执行Manifest的方法,比如说: ```java ClassMethod main(){ //执行Manifest修改命名空间 Set pVars("Namespace")="MYNAMESPACE" $$$ThrowOnError(..ModifyNamespace(.pVars)) //启动IRIS的TELNET服务 set properties("Enabled")=1 // 有効 set sts=##class(Security.Services).Modify("%Service_Telnet",.properties) } ``` 当然,如果您缺乏开发实施的知识,在用户界面上一个个机器的操作是最省心的办法。 问题是,打开一个服务,修改一个配置参数操作都很简单,但是如果要添加大量的用户和权限怎么办? 用Manifest管理是一个办法。但根本上,如果您经常有大量的用户管理的工作,其实使用Kerberos或者LDAP管理用户身份认证和授权的工作, 在有多个镜像成员的情况下,尤其的合适。 关于这部分内容,请参考[在线文档:Authentication and Authorization](https://docs.intersystems.com/iris20231/csp/docbook/DocBook.UI.Page.cls?KEY=PAGE_security_authentication_authorization) ### 定时任务(TASK) 在主机上创建的定时任务, 您需要人工在其他机器上做相同操作。这里有2个步骤: 1. 在主机上创建新任务的时候,要选择”**应如何为镜像运行任务**“。 这是个下拉菜单,选项有*”仅在主镜像成员上运行“,“仅在非主镜像成员上运行“ ,“在任何镜像成员上运行"。* 选择的出发点是:非主镜像成员的数据库是只读的。因此,比如一个Ensemble的镜像配置中, 删除Ensemble消息的定时任务, 一定是”仅在主镜像成员上运行“。 2. 把新的定时任务从主机同步到其他成员。 ​ 如果是一个或者少量几个TASK, 那么手工在其他各个镜像成员上添加是最简单直接的做法。而如果是有很长 的任务列表,尤其在配置Mirror得时候可以需要同步一个长长的列表时, 您可以考虑**从主机导出Task到其 他机器导入**,我只知道使用ObjectScript命令的方法, 使用`%SYS.Task.ExportTask()`和 `%SYS.Task.ImportTasks()`。 文档在[这里](https://docs.intersystems.com/iris20231/csp/documatic/%25CSP.Documatic.cls?LIBRARY=%25SYS&CLASSNAME=%25SYS.Task)。 ### Web Application 主机上配置的Web Applicaiton 也要同步到其他镜像成员。如果要同步的Web Application比较多,推荐的方式依然是Manifest, 下面是一个例子。 ```xml ``` 麻烦的是不同的版本Caché/IRIS使用的标签上会略有不同,要稍微仔细的查看一下您的版本的文档。 如果您对ZPM, 现在称为IPM熟悉的话, 用ZPM做同步也是个好选择。关于zpm, 您可以参考这个帖子[zpm介绍](https://cn.community.intersystems.com/post/zpm%E4%BB%8B%E7%BB%8D1)。提醒一下的是,程序因为是存在数据库里面的,如果该数据库是被镜像的,您其实不需要用ZPM把程序代码拷贝到其他镜像成员。 ### Gateway 一般用到的有**SQL Gateway**和**External Language Gateway**,它们分别用于连接其他的数据库和使用其他语音的代码包。 SQL Gateway 记录保存在%SYS命名空间的*%Library.sys_SQLConnection*数据表里。简单的方法是使用工具把表记录导入导出。 External Language Gateway(外部语言网关) 新版的IRIS系统内嵌了外部语言服务器,包括%Python Server, %Java Server, %Dotnet Server等。如果您使用的是默认配置,各个镜像成员是一致的,无需操心。如果只是IP端口的修改,手工同步一下也很容易,毕竟工作量有限,只是您需要清楚的记得,这个也是不被Mirror自动同步的。 ### 文件 我把文件分为两类, 一类是“固定文件”,包括一下几个部分, - CSP文件,js文件,css文件,html文件等 - XSLT文件 - 其他语言的程序代码,Java文件,python文件, .Net文件 这类文件上传到主机的时候, 也必须上传到其他镜像成员,这是个简单的操作,别忘了就行。 麻烦的是**流文件**。在ObjectScript里如果使用了%Stream.FileBinary, %Stream.FileCharacter等类,那么数据不是保存到Cache.Dat或者IRIS.data, 而是保存在和.Dat同目录的一个stream的子目录下,而这个目录是不会被镜像同步的。 而且,因为这是实时数据,你也不可能手工的把它拷来拷去。 如果您的应用里用到了文件流,我任务您需要一个文件服务器保证流文件在各个各个镜像成员间的同步。 ### Ensemble Production Consideration 对于Ensemble和Health Connect用户,您需要阅读这部分在线文档: [Production Considerations for Mirroring](https://docs.intersystems.com/iris20223/csp/docbook/DocBook.UI.Page.cls?KEY=GHA_mirror_manage#GHA_mirror_set_ensemble) , 简单总结一下: - 创建的带有ensemble或者Inteoprability的命名空间,数据库要创建为Mirror的数据库。 - **"production是否自动启动“**应该在主机和备机上,甚至DR上都配置为“自动启动”。 在Mirror配置下的Production会先检查这个实例是不是主机,如果不是,“自动启动”的配置也不会生效,这样保证了Production只在主机上运行,而切换后也不需要人工干预。 上面的这些并不是完整的内容,尽管在大多少情况下这些内容差不多够了。如果您想要确保Mirror的主机的工作内容完全同步到了备机和DR, 请仔细阅读在线文档的这一部分:[Mirror Configuration Guidelines](https://docs.intersystems.com/iris20223/csp/docbook/DocBook.UI.Page.cls?KEY=GHA_mirror_set_config#GHA_mirror_set_config_guidelines) 另外,对于各种需要人工同步的内容的操作,还建议阅读[在线文档:Server Migration](https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=AMIG#AMIG_migration_external)。 如果是最新的IRIS用户,请参考[在线文档:Deploy Mirrors Using Configuration Merge](https://docs.intersystems.com/iris20223/csp/docbook/DocBook.UI.Page.cls?KEY=GHA_mirror_set_config#GHA_mirror_set_config_auto_merge)