清除过滤器
文章
Michael Lei · 六月 1, 2021
什么是 Data Fabric?
“这是一套用于在公司中实施、管控、管理和执行数据操作的硬件基础架构、软件、工具和资源,功能包括跨所有数据存储平台的数据采集、转换、存储、分发、整合、复制、可用性、安全性、保护、灾难恢复、演示、分析、保存、保留、备份、恢复、归档、召回、删除、监视和容量规划,并可使应用程序的使用满足公司的数据需求”。
(Alan McSweeney)
Data Fabric 是一种可利用包括多模型数据库、Analytics、AI、ESB/SOA、微服务和 API 管理在内的所有可用资源和技术创新来获取商业价值的新型数据操作方法。
Data Fabric 原则
Alan McSweeney 列出了以下 Data Fabric 使用原则:
管控、管理和控制 - 无论数据位于何处,均可掌控数据并能够有效管理和管控数据
稳定性、可靠性和一致性 - 使用通用工具和实用工具在所有数据层之间提供稳定可靠的 Data Fabric
安全性 - 符合 Data Fabric、治理自动化、合规性和风险管理方面的各项安全标准
开放、灵活和自由选择 - 能够选择和更改数据存储、访问权限和位置
自动化 - 自动化管理和维护活动、DevOps 和 DevSecOps
性能、恢复、访问和使用 - 应用程序和用户可以在需要时、根据需求以及以适用格式访问数据
一体化 - 所有组件在所有数据层上均可互操作
Data Fabric 架构
McSweeney 设计了一幅在组织内部采用 Data Fabric 的详细概念图,如下所示:
您可以看到,需要采用某些技术才能将数据输入、处理和输出操作融合到一个流程中,进而“编织”数据并为数据使用者提供业务价值。 这些元素可以概括为下图:
数据操作位于数据接收网关 (Data Intake Gateway) 中,使用 ESB 和 API 网关技术捕获、编排、转换、丰富数据,并将数据资产整合到企业数据资产中。
借助 Analytics 和 AI 处理数据操作结果,从而为数据使用者提供数据分析。
由于数据量庞大且种类繁多,以及人们对于“黄金数据”这一“获得真理的唯一渠道”的需求,因此多模型存储库同样是一个重要角色。
InterSystems IRIS 与 Data Fabric
InterSystems IRIS 是一款支持在组织内部采用 Data Fabric 架构的 Data Fabric 平台,如下文所示:
Data Fabric 组件
InterSystems IRIS 组件
多功能存储库
IRIS 数据库
Java、Python、.NET 和对象脚本中受支持的 SQL Relational 对象
NoSQL 到 JSON – DocDB
可以使用 MDX 多维数据集进行分析
分片支持以支持大数据(与 MongoDB 相同)
企业缓存 – ECP
通过集成总线实现的 MDM
RBAC、密码学和标签
Transanalytic 和数据湖
使用 ORM 进行对象脚本的 JDBC、ODBC 或本机 SQL 访问
通过集成总线/服务总线和 API 网关实现数据接收/网关
IRIS 互操作性
REST API 和 API 管理
数据总线 - SOA、EAI、ESB
集成和 EDI 适配器
流程自动化 - BPL 和 DTL、规则
原生集成 Java、.NET 和 C Python 和 JavaScript
MFT - 托管文件传输
消息、事件和 JMS
采用 MQTT/API 的物联网
数据抽取/引入、转换和加载
分析和报告实用工具
IRIS Analytics
BI/分析和 ETL (BPL/DTL)
分级面板、分析和数据透视
SQL、MDX 和 Power BI 连接器访问
报告和嵌入式报告
UIMA - 非结构化内容分析
语义和情感分析
实时或计划分析
AutoML – IntegratedML
采用 R 或 Pyhton 的 AI/机器学习
NLP - 自然语言处理
R 、Python 和对象脚本中的统计信息
数据总线和认知流
文本分析
PMML
自适应运营分析 (AtScale)
用户门户
AI 实用工具
## 结语
InterSystems IRIS 并非简单的数据库或互操作平台,而是帮助您实现 Data Fabric 的核心角色。 如果您使用其他公司的其他解决方案,则需要购买 4 至 7 套解决方案,但使用 InterSystems,您只需要由多模型数据库、ESB/APIM、Analytics 和 AI 组成的一套解决方案即可创建 Data Fabric。 它为您提供了价格低廉、易于使用的优势。
了解详情:
文章
姚 鑫 · 五月 31, 2021
# 第十二章 IBM WebSphere MQ检索邮件
# 检索邮件
要检索邮件,请执行以下操作:
1. 按照“创建连接对象”中的说明创建连接对象。在这种情况下,请创建`%Net.MQRecv`的实例。`Connection`对象有一个消息队列,可以从中检索消息。
2. 根据需要调用以下方法:
- `%Get()`-通过引用返回字符串消息作为第一个参数。
- `%GetStream()`-给定初始化的文件字符流,此方法从队列中检索消息,并将其放入与该流关联的文件中。请注意,必须设置流的`Filename`属性才能对其进行初始化。不支持二进制流。
3. 检查调用的方法返回的值。请参阅“获取错误代码”。请记住,当队列为空时,IBM `WebSphere MQ`返回`2033`。
4. 检索完消息后,调用`Connection`对象的`%Close()`方法以释放动态链接库的句柄。
示例1:`ReceiveString()`
下面的类方法从`mqtest`队列检索消息。
```java
///Method returns string or null or error message
ClassMethod ReceiveString() As %String
{
Set recv=##class(%Net.MQRecv).%New()
Set queue="mqtest"
Set qm="QM_antigua"
Set chan="S_antigua/TCP/antigua(1414)"
Set logfile="c:\mq-recv-log.txt"
Set check=recv.%Init(queue,qm,chan,logfile)
If 'check Quit recv.%GetLastError()
Set check=recv.%Get(.msg)
If 'check {
Set reasoncode=recv.%GetLastError()
If reasoncode=2033 Quit ""
Quit "ERROR: "_reasoncode
}
Quit msg
}
```
示例2:`ReceiveCharacterStream()`
以下方法可以检索更长的消息,因为它使用`%GetStream()`:
```java
/// Method returns reason code from IBM WebSphere MQ
ClassMethod ReceiveCharacterStream() As %Integer
{
Set recv=##class(%Net.MQRecv).%New()
Set queue="mqtest"
Set qm="QM_antigua"
Set chan="S_antigua/TCP/antigua(1414)"
Set logfile="c:\mq-recv-log.txt"
Set check=recv.%Init(queue,qm,chan,logfile)
If 'check Quit recv.%GetLastError()
//initialize the stream and tell it what file to use
//make sure filename is unique we can tell what we received
Set longmsg=##class(%FileCharacterStream).%New()
Set longmsg.Filename="c:\mq-received"_$h_".txt"
Set check=recv.%GetStream(longmsg)
If 'check Quit recv.%GetLastError()
Quit check
}
```
# 更新消息信息
`%Net.MQSend`和`%Net.MQRecv`类还提供以下方法:
### %CorId()
(通过引用)更新上次读取的邮件的关联ID。
### %ReplyQMgrName()
(通过引用)更新上次读取的消息的回复队列管理器名称。
### %ReplyQName()
(通过引用)更新上次读取的消息的回复队列名称。
# Troubleshooting
如果在使用IBM `WebSphere MQ`的InterSystems IRIS接口时遇到问题,应该首先确定客户端是否安装正确并且可以与服务器通信。要执行这样的测试,可以使用IBM `WebSphere MQ`提供的示例程序。可执行文件位于IBM `WebSphere MQ`客户端的bin目录中。
以下步骤介绍如何在`Windows`上使用这些示例程序。在其他操作系统上,细节可能会有所不同;请参考IBM文档并检查您的客户端中存在的文件的名称。
1. 创建一个名为`MQSERVER`的环境变量。它的值的格式应该是`channel_name/Transport/server`,其中`channel_name`是要使用的通道的名称,`Transport`是指示要使用的传输的字符串,而`server`是服务器的名称。例如:`S_Antigua/TCP/Antigua`
2. 在命令行中,输入以下命令:
```java
amqsputc queue_name queue_manager_name
```
其中,`QUEUE_NAME`是要使用的队列的名称,`QUEUE_MANAGER_NAME`是队列管理器的名称。例如:
```java
amqsputc mqtest QM_antigua
```
如果`amqsputc`命令无法识别,请确保已更新`PATH`环境变量以包括IBM `WebSphere MQ`客户端的bin目录。
3. 应该会看到几行代码,如下所示:
```java
Sample AMQSPUT0 start
target queue is mqtest
```
4. 现在可以发送消息了。只需键入每条消息,然后在每条消息后按Enter键即可。例如:
```java
sample message 1
sample message 2
```
5. 发送完邮件后,按两次Enter键。然后,将看到如下所示的行:
```java
Sample AMQSPUT0 end
```
6. 要完成此测试,我们将检索发送到队列的消息。在命令行中键入以下命令:
```java
amqsgetc queue_name queue_manager_name
```
其中,`QUEUE_NAME`是要使用的队列的名称,`QUEUE_MANAGER_NAME`是队列管理器的名称。例如:
7. 然后,应该看到一个起始行,后跟之前发送的消息,如下所示:
```java
Sample AMQSGET0 start
message
message
```
8. 此示例程序短暂等待接收任何其他消息,然后显示以下内容:
```java
no more messages
Sample AMQSGET0 end
```
如果测试失败,请参考IBM文档。问题的可能原因包括以下几个方面:
- 安全问题
- 队列定义不正确
- 队列管理器未启动
文章
Louis Lu · 五月 30, 2021
本文主要总结了在InterSystems IRIS 中如何保存、查询List类型数据
假设我们设计的对象中包含姓名,同时每个姓名下可以包含多个电话。我们可以使用下面方法进行处理。
1. 传统方式
我们可以把每一个姓名和电话放在不同列中。
Class Test.Person Extends %Persistent
{
Property Name As %String;
Property Phone As %String;
}
我们使用SQL语句插入数据:
insert into Test.Person values ('a','111-111-1111');
insert into Test.Person values ('b','222-111-1111');
insert into Test.Person values ('a','111-222-1111');
insert into Test.Person values ('c','333-111-1111');
insert into Test.Person values ('b','222-222-1111');
数据在表中是这样的:
Name
Phone
a
111-111-1111
b
222-111-1111
a
111-222-1111
c
333-111-1111
b
222-222-1111
这种情况下,我们可以使用下面的sql语句将结果返回:
SELECT
distinct %exact(Name) Name,
LIST(phone %foreach(Name)) Phonestr
FROM test.person
Name
Phonestr
a
111-111-1111,111-222-1111
b
222-111-1111,222-222-1111
c
333-111-1111
我们可以为电话号码创建索引,以提高搜索速度,如下:
Index IdxP On Phone;
使用这种方式保存list数据比较简单,当是当list数据非常多时,这种方法会使表格臃肿。
2. 保存在一个字符串字段中,使用分隔符区分
这里我们将所有电话号码保存在一个字符串字段中,每个号码之间用逗号区分
Class Test.Person2 Extends %Persistent
{
Property Name As %String;
Property PhoneStr As %String;
}
填充数据后,类似于这样
Name
PhoneStr
a
111-111-1111,111-222-1111
b
222-111-1111,222-222-1111
c
333-111-1111
d
333-111-1111,222-222-1111
这种情况下我们可以用下面方法实现对每个电话的索引
Index idxP On PhoneStr(ELEMENTS);
ClassMethod PhoneStrBuildValueArray(value, ByRef array) As %Status
{
if value="" {
s array(0)=value
}else{
s list=$lfs(value,","),ptr=0
while $listnext(list,ptr,item){
s array(ptr)=item
}
}
q $$$OK
}
这里用到了一个函数
ClassMethod propertynameBuildValueArray(value, ByRef valueArray) As %Status
其中:
value – 需要拆分的内容;
valueArray – 返回array类型的值,其中包含拆分的内容,格式为 array(key1)=value1, array(key2)=value2...
这时候我们的数据是这样:
USER>zw ^Test.Person2D
^Test.Person2D=4
^Test.Person2D(1)=$lb("","a","111-111-1111,111-222-1111")
^Test.Person2D(2)=$lb("","b","222-111-1111,222-222-1111")
^Test.Person2D(3)=$lb("","c","333-111-1111")
^Test.Person2D(4)=$lb("","d","333-111-1111,222-222-1111")
索引是这样:
USER>zw ^Test.Person2I
^Test.Person2I("idxP"," 111-111-1111",1)=""
^Test.Person2I("idxP"," 111-222-1111",1)=""
^Test.Person2I("idxP"," 222-111-1111",2)=""
^Test.Person2I("idxP"," 222-222-1111",2)=""
^Test.Person2I("idxP"," 222-222-1111",4)=""
^Test.Person2I("idxP"," 333-111-1111",3)=""
^Test.Person2I("idxP"," 333-111-1111",4)=""
这种情况下我们可以通过下面的SQL 语句查找 包含电话号码 333-111-1111 的姓名
select Name from test.person2 where phonestr ['333-111-1111'
select Name from test.person2 where phonestr like '%333-111-1111%'
但是当你检查查询计划的时候,却发现它并没有使用任何索引
我们只能通过类似于下面SQL语句的写法才能使用该索引
select Name from test.person2 where for some %element(Phonestr) (%value = '333-111-1111')
类似的还有下面的写法
(%Value %STARTSWITH 'а')
(%Value [ 'a' and %Value [ 'b')
(%Value in ('c','d'))
(%Value is null)
3. 使用 %List 类型
Class Test.Person3 Extends %Persistent
{
Property Name As %String;
Property PhoneList As %List;
Index idxP On PhoneList(ELEMENTS);
ClassMethod PhoneListBuildValueArray(value, ByRef array) As %Status
{
if value="" {
s array(0)=value
}else{
s ptr=0
while $listnext(value,ptr,item){
s array(ptr)=item
}
}
q $$$OK
}
}
插入数据
insert into Test.Person3 (Name,PhoneList) select 'a', $LISTBUILD('111-111-1111','111-222-1111')
insert into Test.Person3 (Name,PhoneList) select 'b', $LISTBUILD('222-111-1111','222-222-1111')
insert into Test.Person3 (Name,PhoneList) select 'c', $LISTBUILD('333-111-1111')
insert into Test.Person3 (Name,PhoneList) select 'd', $LISTBUILD('333-111-1111','222-222-1111')
数据和索引保存为
USER>zw ^Test.Person3D
^Test.Person3D=4
^Test.Person3D(1)=$lb("","a",$lb("111-111-1111","111-222-1111"))
^Test.Person3D(2)=$lb("","b",$lb("222-111-1111","222-222-1111"))
^Test.Person3D(3)=$lb("","c",$lb("333-111-1111"))
^Test.Person3D(4)=$lb("","d",$lb("333-111-1111","222-222-1111"))
USER>zw ^Test.Person3I
^Test.Person3I("idxP","111-111-1111",1)=""
^Test.Person3I("idxP","111-222-1111",1)=""
^Test.Person3I("idxP","222-111-1111",2)=""
^Test.Person3I("idxP","222-222-1111",2)=""
^Test.Person3I("idxP","222-222-1111",4)=""
^Test.Person3I("idxP","333-111-1111",3)=""
^Test.Person3I("idxP","333-111-1111",4)=""
同样可以使用下面的SQL语句查找包含电话333-111-1111的姓名
select Name from test.person2 where for some %element(phonelist) (%value = '333-111-1111')
4 使用 List Of、Array Of 保存
不需要定义propertynameBuildValueArray函数
Class Test.Person4 Extends %Persistent
{
Property Name As %String;
Property PhoneList As list Of %String;
Index idxP On PhoneList(ELEMENTS);
}
使用同样的方式插入数据
insert into Test.Person4 (Name,PhoneList) select 'a', $LISTBUILD('111-111-1111','111-222-1111')
insert into Test.Person4 (Name,PhoneList) select 'b', $LISTBUILD('222-111-1111','222-222-1111')
insert into Test.Person4 (Name,PhoneList) select 'c', $LISTBUILD('333-111-1111')
insert into Test.Person4 (Name,PhoneList) select 'd', $LISTBUILD('333-111-1111','222-222-1111')
数据和索引保存为
USER>zw ^Test.Person4D
^Test.Person4D=4
^Test.Person4D(1)=$lb("","a",$lb("111-111-1111","111-222-1111"))
^Test.Person4D(2)=$lb("","b",$lb("222-111-1111","222-222-1111"))
^Test.Person4D(3)=$lb("","c",$lb("333-111-1111"))
^Test.Person4D(4)=$lb("","d",$lb("333-111-1111","222-222-1111"))
USER>zw ^Test.Person4I
^Test.Person4I("idxP"," 111-111-1111",1)=""
^Test.Person4I("idxP"," 111-222-1111",1)=""
^Test.Person4I("idxP"," 222-111-1111",2)=""
^Test.Person4I("idxP"," 222-222-1111",2)=""
^Test.Person4I("idxP"," 222-222-1111",4)=""
^Test.Person4I("idxP"," 333-111-1111",3)=""
^Test.Person4I("idxP"," 333-111-1111",4)=""
使用同样的SQL查询可以得到结果
select Name from test.person4 where for some %element(Phonelist) (%value = '333-111-1111')
引申话题:针对日期字段的索引
日期格式通常是yyyy-mm-dd,我们经常要求按照某年或者某月查询数据,我们可以使用propertynameBuildValueArray函数设定保存的索引方式实现这个目的
Class Test.Person5 Extends %Persistent
{
Property Name As %String;
Property DOB As %Date;
Index idxD On (DOB(KEYS), DOB(ELEMENTS));
ClassMethod DOBBuildValueArray(value, ByRef array) As %Status
{
if value="" {
s array(0)=value
}else{
s d=$zd(value,3)
s array("yy")=+$p(d,"-",1)
s array("mm")=+$p(d,"-",2)
s array("dd")=+$p(d,"-",3)
}
q $$$OK
}
}
插入数据
insert into Test.Person5 (Name,DOB)
select 'a', {d '2000-01-01'} union all
select 'b', {d '2000-01-02'} union all
select 'c', {d '2000-02-01'} union all
select 'd', {d '2001-01-02'} union all
select 'e', {d '2001-01-01'} union all
select 'f', {d '2001-02-01'}
查看数据以及索引保存的内容
USER>zw ^Test.Person5D
^Test.Person5D=6
^Test.Person5D(1)=$lb("","a",58074)
^Test.Person5D(2)=$lb("","b",58075)
^Test.Person5D(3)=$lb("","c",58105)
^Test.Person5D(4)=$lb("","d",58441)
^Test.Person5D(5)=$lb("","e",58440)
^Test.Person5D(6)=$lb("","f",58471)
USER>zw ^Test.Person5I
^Test.Person5I("idxD","dd",1,1)=""
^Test.Person5I("idxD","dd",1,3)=""
^Test.Person5I("idxD","dd",1,5)=""
^Test.Person5I("idxD","dd",1,6)=""
^Test.Person5I("idxD","dd",2,2)=""
^Test.Person5I("idxD","dd",2,4)=""
^Test.Person5I("idxD","mm",1,1)=""
^Test.Person5I("idxD","mm",1,2)=""
^Test.Person5I("idxD","mm",1,4)=""
^Test.Person5I("idxD","mm",1,5)=""
^Test.Person5I("idxD","mm",2,3)=""
^Test.Person5I("idxD","mm",2,6)=""
^Test.Person5I("idxD","yy",2000,1)=""
^Test.Person5I("idxD","yy",2000,2)=""
^Test.Person5I("idxD","yy",2000,3)=""
^Test.Person5I("idxD","yy",2001,4)=""
^Test.Person5I("idxD","yy",2001,5)=""
^Test.Person5I("idxD","yy",2001,6)=""
执行下面 SQL 可以显示所有2月出生的信息
select * from Test.Person5 where for some %element(DOB) (%key='mm' and %value = 2)
这篇文章源自 这里,作者 Vitaliy Serdtsev
文章
姚 鑫 · 五月 30, 2021
# 第十一章 发送和接收IBM WebSphere MQ消息
InterSystems IRIS为IBM `WebSphere MQ`提供了一个接口,可以使用该接口在InterSystems IRIS和IBM `WebSphere MQ`的消息队列之间交换消息。要使用此接口,必须能够访问IBM `WebSphere MQ`服务器,并且IBM `WebSphere MQ`客户端必须与InterSystems IRIS在同一台计算机上运行。
该接口由`%Net.MQSend`和`%Net.MQRecv`类组成,这两个类都是`%Net.abstractMQ`的子类。这些类使用由InterSystems IRIS在所有合适的平台上自动安装的动态链接库。(这是Windows上的`MQInterface.dll`;其他平台的文件扩展名不同。)。反过来,InterSystems IRIS动态链接库需要IBM `WebSphere MQ`动态链接库。
该界面仅支持发送和接收文本数据,不支持二进制数据。
# 使用IBM WebSphere MQ的RIS接口
通常,要使用IBM `WebSphere MQ`的InterSystems IRIS接口,请执行以下操作:
1. 确保有权访问`IBM WebSphereMQv7.x`或更高版本。具体而言:
- IBM `WebSphere MQ`客户端必须与InterSystems IRIS安装在同一台计算机上。请注意,安装程序会根据需要更新`PATH`环境变量并添加其他系统变量。
- 确保在安装客户端后重新启动计算机,以便InterSystems IRIS能够识别该客户端。
- 客户端必须能够访问IBM `WebSphere MQ`服务器。
- 将用来访问服务器的用户名必须具有使用队列管理器和计划使用的队列的权限。
2. 创建`%Net.MQSend`或`%Net.MQRecv`的新实例,具体取决于要发送还是接收消息。
3. 连接到IBM `WebSphere MQ`服务器。执行此操作时,您需要提供以下信息:
- 队列管理器的名称。
- 要使用的队列的名称。
- 与该队列通信的通道。可以指定IBM `WebSphere MQ`服务器的通道名称、传输机制以及IP地址和端口。
如果正在使用IBM `WebSphere MQ`的身份验证功能,还可以提供名称和密码。
4. 调用`%Net.MQSend`或`%Net.MQRecv`的相应方法来发送或接收消息。
注意:要在64位Linux平台上使用IBM `Websphere MQ`,必须设置`LD_LIBRARY_PATH`以包括`MQ`库的位置。因为必须为任何使用`MQ`接口的InterSystems IRIS进程设置路径,所以如果正在运行后台进程,则必须在启动InterSystems IRIS之前设置该路径,并在运行IRIS终端之前在任何UNIX®终端中设置该路径。
## 获取错误代码
`%Net.MQSend`和`%Net.MQRecv`的方法如果成功则返回1,如果不成功则返回0。在出现错误的情况下,调用`%GetLastError()`方法,该方法返回IBM `WebSphere MQ`给出的最后一个原因代码。
# 创建连接对象
在可以通过IBM `WebSphere MQ`发送或接收消息之前,必须创建一个`Connection`对象,该对象可以建立到队列管理器的连接、打开通道和打开队列以供使用。有两种方法可以做到这一点:
- 可以使用`%Init`方法,该方法接受指定所有所需信息的参数。
- 可以在首次设置指定所有所需信息的属性后使用`%Connect`方法。
## 使用%Init()方法
要使用`%Init()`方法创建连接对象,请执行以下操作:
1. 创建`%Net.MQSend`(如果要发送消息)或`%Net.MQRecv`(如果要接收消息)的实例。本主题将此实例称为连接对象。
注意:如果收到 ``错误,则表示缺少动态链接库,并且`messages.log`文件(在系统管理器的目录中)有更多详细信息。
2. 如果需要身份验证,请设置`Connection`对象的以下属性:
- 用户名-指定有权使用此频道的用户名。
- 密码-指定给定用户的密码。
3. 调用`Connection`对象的`%Init()`方法。此方法按顺序接受以下参数。
a. 指定队列名称的字符串;这应该是指定队列管理器的有效队列。
b. 指定队列管理器的字符串;它应该是IBM `WebSphere MQ`服务器上的有效队列管理器。
如果省略此参数,系统将使用IBM `WebSphere MQ`中配置的默认队列管理器。或者,如果IBM `WebSphere MQ`已配置为队列管理器由队列名称确定,则系统将使用适合给定队列名称的队列管理器。
c. 指定频道规范的字符串,格式如下:
```java
"channel_name/transport/host_name(port)"
```
这里,`channel_name`是要使用的通道的名称,`Transport`是通道使用的传输,`host_name`是运行IBM `WebSphere MQ`服务器的服务器名称(或IP地址),`port`是该通道应该使用的端口。
传输可以是以下之一:`TCP`、`LU62`、`NETBIOS`、`SPX`
例如:
```java
"CHAN_1/TCP/rodan(1401)"
```
```java
"CHAN_1/TCP/127.0.0.1(1401)"
```
如果省略此参数,系统将使用IBM `WebSphere MQ`中配置的默认通道规范。或者,如果系统已配置为通道由队列名称确定,则系统使用适合给定队列名称的通道。
d. 一个可选字符串,它指定要向其中写入错误消息的日志文件。默认情况下,不进行日志记录。
4. 检查`%Init()`方法返回的值。如果该方法返回1,则表明连接已成功建立,可以使用`Connection`对象发送或接收消息(具体取决于使用的类)。
## 使用%Connect()方法
在某些情况下,可能更喜欢单独指定连接的所有详细信息。为此,请使用`%Connect()`方法,如下所示:
1. 创建`%Net.MQSend`(如果要发送消息)或`%Net.MQRecv`(如果要接收消息)的实例。如前所述,本主题将此实例称为连接对象。
注意:如果收到`` 错误,则表示缺少动态链接库,并且`messages.log`文件(在系统管理器的目录中)有更多详细信息。
2. 设置`Connection`对象的以下属性:
- `QName`-(必选)指定队列名称;这应该是指定队列管理器的有效队列。
- `QMgr`-指定要使用的队列管理器;它应该是IBM `WebSphere MQ`服务器上的有效队列管理器。
如果省略此参数,系统将使用IBM `WebSphere MQ`中配置的默认队列管理器。或者,如果IBM `WebSphere MQ`已配置为队列管理器由队列名称确定,则系统将使用适合给定队列名称的队列管理器。
3. 或者,通过设置`Connection`对象的以下属性来指定要使用的频道:
- `Connection` - 指定IBM `WebSphere MQ`服务器的主机和端口。例如:`"127.0.0.1:1401"`。
- `Channel` - 指定要使用的频道的名称。这必须是IBM WebSphere MQ服务器上的有效通道。
- `Transport` - 指定通道使用的传输。此属性可以是以下之一: `"TCP"`, `"LU62"`, `"NETBIOS"`, `"SPX"`
如果省略这些参数,系统将使用IBM `WebSphere MQ`中配置的默认通道规范。或者,如果系统已配置为通道由队列名称确定,则系统使用适合给定队列名称的通道。
4. 如果频道需要身份验证,请设置`Connection`对象的以下属性:
- 用户名-指定有权使用此频道的用户名。
- 密码-指定给定用户的密码。
5. 调用`Connection`对象的`%ErrLog()`方法。此方法接受一个参数,即要用于此连接对象的日志文件的名称。
6. 检查`%ErrLog()`方法返回的值。
7. 调用`Connection`对象的`%Connect()`方法。
8. 检查`%Connect()`方法返回的值。如果该方法返回1,则表明连接已成功建立,可以使用`Connection`对象发送或接收消息(具体取决于您使用的类)。
# 指定字符集(CCSID)
要设置用于消息转换的字符集,请调用`Connection`对象的`%SetCharSet()`方法。指定在IBM `WebSphere MQ`中使用的整数编码字符集`ID(CCSID)`。
- 如果正在发送消息,这应该是这些消息的字符集。如果不指定字符集,则MQ系统假定消息使用为`MQ`客户端指定的默认字符集。
- 如果要检索邮件,则这是要将这些邮件翻译为的字符集。
要获取当前正在使用的`CCSID`,请调用`%charset()`方法。此方法通过引用返回`CCSID`,并返回1或0以指示是否成功.
# 指定其他消息选项
要指定消息描述符选项,可以选择设置连接对象的以下属性:
- `ApplIdentityData`指定应用程序标识消息描述符选项。
- `PutApplType`指定`PUT Application Type`消息描述符选项。
## 发送消息
要发送邮件,请执行以下操作:
1. 按照“创建连接对象”中的说明创建连接对象。在这种情况下,请创建`%Net.MQSend`的实例。`Connection`对象有一个消息队列,可以向该队列发送消息。
2. 根据需要调用以下方法:
- `%put()`-给定一个字符串,此方法将该字符串写入消息队列。
- `%PutStream()`-给定初始化的文件字符流,此方法将该字符串写入消息队列。请注意,必须设置流的`Filename`属性才能对其进行初始化。不支持二进制流。
- `%SetMsgId()`-给定一个字符串,此方法使用该字符串作为发送的下一条消息的消息ID。
3. 检查调用的方法返回的值。
4. 检索完消息后,调用`Connection`对象的`%Close()`方法以释放动态链接库的句柄。
示例1:`SendString()`
下面的类方法使用队列管理器`QM_antigua`和名为 `S_antigua`的队列通道向队列`mqtest`发送一条简单的字符串消息。通道使用TCP传输,IBM `WebSphere MQ`服务器运行在名为`Antigua`的机器上,并侦听端口1401。
```java
///Method returns reason code from IBM WebSphere MQ
ClassMethod SendString() As %Integer
{
Set send=##class(%Net.MQSend).%New()
Set queue="mqtest"
Set qm="QM_antigua"
Set chan="S_antigua/TCP/antigua(1414)"
Set logfile="c:\mq-send-log.txt"
Set check=send.%Init(queue,qm,chan,logfile)
If 'check Quit send.%GetLastError()
//send a unique message
Set check=send.%Put("This is a test message "_$h)
If 'check Quit send.%GetLastError()
Quit check
}
```
示例2:`SendCharacterStream()`
下面的类方法发送文件字符流的内容。它使用的队列与上一个示例中使用的队列相同:
```java
///Method returns reason code from IBM WebSphere MQ
ClassMethod SendCharacterStream() As %Integer
{
Set send=##class(%Net.MQSend).%New()
Set queue="mqtest"
Set qm="QM_antigua"
Set chan="S_antigua/TCP/antigua(1414)"
Set logfile="c:\mq-send-log.txt"
Set check=send.%Init(queue,qm,chan,logfile)
If 'check Quit send.%GetLastError()
//initialize the stream and tell it what file to use
Set longmsg=##class(%FileCharacterStream).%New()
Set longmsg.Filename="c:\input-sample.txt"
Set check=send.%PutStream(longmsg)
If 'check Quit send.%GetLastError()
Quit check
}
```
示例3:从终端发送消息
以下示例显示了向IBM `WebSphere MQ`队列发送消息的终端会话。这只能在配置了IBM `WebSphere MQ`客户端的计算机上运行。
```java
Set MySendQ = ##class(%Net.MQSend).%New()
Do MySendQ.%Init("Q_1", "QM_1","QC_1/TCP/127.0.0.1(1401)","C:\mq.log")
Do MySendQ.%Put("Hello from tester")
Set MyRecvQ =##class(%Net.MQRecv).%New()
Do MyRecvQ.%Init("Q_1", "QM_1","QC_1","C:\mq.log")
Do MyRecvQ.%Get(.msg, 10000)
Write msg,!
```
文章
姚 鑫 · 五月 29, 2021
# 第十章 使用FTP
IRIS提供了一个类`%Net.FtpSession`,可以使用它从InterSystems IRIS内建立与FTP服务器的会话。
# 建立FTP会话
要建立FTP会话,请执行以下操作:
1. 创建`%Net.FtpSession`的实例。
2. 可以选择设置此实例的属性,以控制会话的常规行为:
- `Timeout` 超时指定等待FTP服务器回复的时间(以秒为单位)。
- `SSLConfiguration`指定用于连接的激活的`SSL/TLS`配置(如果有)。如果`FTP`服务器使用HTTPS,请使用此选项。
- `TranslateTable`指定在读取文件内容或写入文件内容时要使用的转换表。
- `UsePASV`启用PASV模式。
- 当`FTP`服务器使用`https`时,`SSLCheckServerIdentity`适用。默认情况下,当`%Net.FtpSession`的实例连接到`SSL/TLS`服务器时,它会检查证书服务器名称是否与用于连接到服务器的DNS名称匹配。如果这些名称不匹配,则不允许连接。
若要禁用此检查,请将`SSLCheckServerIdentity`属性设置为0。
3. 调用`Connect()`方法以连接到特定的FTP服务器。
4. 调用`ascii()`或`binary()`方法将传输模式分别设置为ASCII模式或二进制模式。要查看当前传输模式,请检查实例的Type属性的值。
注意:`%Net.FtpSession`的每个方法都返回一个状态,应该检查该状态。这些方法还设置提供有关会话状态的有用信息的属性的值:
- 如果当前已连接,则`CONNECTED`为TRUE,否则为FALSE。
- `ReturnCode`包含上次与FTP服务器通信时的返回代码。
- `ReturnMessage`包含上次与FTP服务器通信时的返回消息。
`Status()`方法返回(通过引用)FTP服务器的状态。
## 命令的转换表
`%Net.FtpSession`在FTP服务器上查看文件名和路径名时,使用`RFC 2640`中介绍的技术自动处理字符集转换。当`%Net.FtpSession`的实例连接到FTP服务器时,它会使用Feat消息来确定服务器是否使用`UTF-8`字符。如果是,它将命令通道通信切换到`UTF-8`,以便所有文件名和路径名都可以正确地与`UTF-8`相互转换。
如果服务器不支持`FEAT`命令或未报告支持`UTF-8`,`%Net.FtpSession`实例将使用`RAW`模式并读取或写入RAW字节。
在极少数情况下,如果需要指定要使用的转换表,请设置`%Net.FtpSession`实例的`CommandTranslateTable`属性。一般情况下,应该没有必要使用此属性。
# FTP文件和系统方法
一旦建立了FTP会话,就可以调用会话实例的方法来执行FTP任务。`%Net.FtpSession`提供以下读写文件的方法:
### Delete()
删除文件。
### Retrieve()
将文件从FTP服务器复制到InterSystems IRIS流中,并通过引用返回该流。要使用此流,请使用标准流方法:`Write()`、`WriteLine()`、`Read()`、`ReadLine()`、`Rewind()`、`MoveToEnd()`和`Clear()`。还可以使用流的`Size`属性。
### RetryRetrieve()
允许继续检索文件,因为给定的流是由上一次使用`Retrieve()`创建的。
### Store()
将 IRIS流的内容写入FTP服务器上的文件。
### Append()
将流的内容追加到指定文件的末尾。
### Rename()
重命名文件。
此外,`%Net.FtpSession`提供了导航和修改FTP服务器上的文件系统的方法:`GetDirectory()`、`SetDirectory()`、`SetToParentDirectory()`和`MakeDirectory()`。
要检查文件系统的内容,请使用`list()`或`NameList()`方法。
- `List()`创建一个流,其中包含其名称与给定模式匹配的所有文件的列表,并通过引用返回该流。
- `NameList()`创建文件名数组并通过引用返回该数组。
还可以使用`ChangeUser()`方法更改为其他用户;这比注销并再次登录要快。使用`Logout()`方法注销。
`System()`方法返回(通过引用)有关托管FTP服务器的计算机类型的信息。
`Size()`和`MDTM()`方法分别返回文件的大小和修改时间。
使用通用`sendCommand()`方法向FTP服务器发送命令并读取响应。此方法可用于发送`%Net.FtpSession`中未明确支持的命令。
# 使用链接的流上载大文件
如果要上传大文件,请考虑使用流接口的`LinkToFile()`方法。也就是说,不是创建流并将文件读入其中,而是创建流并将其链接到文件。在调用`%Net.FtpSession`的`Store()`方法时使用此链接流。
```java
Method SendLargeFile(ftp As %Net.FtpSession, dir As %String, filename As %String)
{
Set filestream=##class(%FileBinaryStream).%New()
Set sc=filestream.LinkToFile(dir_filename)
If $$$ISERR(sc) {do $System.Status.DisplayError(sc) quit }
//上传的文件将与原始文件同名
Set newname=filename
Set sc=ftp.Store(newname,filestream)
If $$$ISERR(sc) {do $System.Status.DisplayError(sc) quit }
}
```
# 自定义FTP服务器发出的回调
可以自定义`FTP`服务器生成的回调。例如,通过这样做,可以向用户提供服务器仍在处理大型传输的指示,或允许用户中止传输。
要自定义FTP回调,请执行以下操作:
1. 创建`%Net.FtpCallback`的子类。
2. 在这个子类中,实现`RetrieveCallback()`方法,该方法在从FTP服务器接收数据时定期调用。
3. 还要实现`StoreCallback()`方法,在将数据写入FTP服务器时会定期调用该方法。
4. 创建`FTP`会话时(如“建立FTP会话”中所述),将回调属性设置为等于的子类`%Net.FtpCallback`。
文章
姚 鑫 · 五月 27, 2021
# 第八章 处理收到的电子邮件
# 处理收到的电子邮件
本节介绍如何处理通过`%Net.POP3`检索到的电子邮件(`%Net.MailMessage`)。
## Message Basics
检索电子邮件(`%Net.MailMessage`)后,通常首先确定它是哪种类型的邮件以及如何阅读它;也就是说,它是否是多部分邮件以及各部分是否是二进制的。在此步骤中,您可以使用`ContentType`属性。或者,可以使用`IsBinary`、`IsHTML`和`IsMultiPart`属性,它们间接提供与`contentType`相同的信息。
如果消息是多部分消息,则每个部分都是`%Net.MailMessagePart`的一个实例。
## Message Headers
消息本身和消息的每个部分都有一组标头。
`%Net.MailMessage`和`%Net.MailMessagePart`类提供的属性使可以轻松访问最常用的标头。例如,`%Net.MailMessage`提供收件人、发件人、主题和日期等属性。`Headers`数组属性允许访问任何自定义标题.
此外,如果已通过`%Net.POP3`检索到消息,则可以使用`GetAttribute()`方法。在给定标头名称和属性的情况下,此方法返回该属性的值。
## Message Contents
了解常规消息结构后,请使用以下技术检索内容:
- 对于多部分消息,请使用`Parts`属性,该属性是部分的数组。`Parts.Count()`给出部件的数量。每个部件的键都是一个整数,从1开始。使用`GetAt()`方法检索给定的部件。消息部分是`%Net.MailMessagePart`的实例。
- 对于二进制消息(或消息部分),请使用`BinaryData`属性。
- 对于文本消息(或消息部分),请使用`TextData`属性。
- 如果`IsHTML`为0,则`TextData`属性为普通文本字符串。
- 如果`IsHTML`为1,则`TextData`属性为HTML文本字符串。
请注意,发送邮件的电子邮件客户端确定邮件中的任何包装。邮件服务器无法控制这一点,
## 其他消息信息
`MessageSize`属性表示邮件的总长度(不包括任何附加的电子邮件)。
以下方法提供有关消息的其他信息:
### GetLocalDateTime()
返回检索消息的日期和时间,并转换为`$HOROLOG`格式的本地时间。
### GetUTCDateTime()
返回检索消息的日期和时间,并以`$HOROLOG`格式转换为UTC。
### GetUTCSeconds()
返回自1840年12月31日以来检索消息的日期和时间(秒)。
以下类方法也可用于时间/日期转换:
### HToSeconds()
将`$HOROLOG`格式的日期/时间转换为自1840年12月31日以来的秒的类方法。
### SecondsToH()
将自1840年12月31日以来的秒数转换为`$HOROLOG`格式的日期/时间的类方法。
示例1:`ShowMsgInfo()`
```java
ClassMethod ShowMsgInfo(msg as %Net.MailMessage)
{
Write "Message details *****",!
Write "To (count): ", msg.To.Count(),!
Write "From: ", msg.From,!
Write "Cc (count): ", msg.Cc.Count(),!
Write "Bcc (count): ", msg.Bcc.Count(),!
Write "Date: ", msg.Date,!
Write "Subject: ", msg.Subject,!
Write "Sender: ", msg.Sender,!
Write "IsMultipart: ", msg.IsMultiPart,!
Write "Number of parts: ", msg.Parts.Count(),!
Write "Number of headers: ", msg.Headers.Count(),!
Write "IsBinary: ", msg.IsBinary,!
Write "IsHTML: ", msg.IsHTML,!
Write "TextData: ", msg.TextData.Read(),!
Write "BinaryData: ", msg.BinaryData.Read(),!
}
```
此方法产生类似于以下内容的输出:
```java
Message details *****
To (count): 1
From: "XXX XXX"
Cc (count): 0
Bcc (count): 0
Date: Fri, 16 Nov 2007 11:57:46 -0500
Subject: test 5
Sender:
IsMultipart: 0
Number of parts: 0
Number of headers: 16
IsBinary: 0
IsHTML: 0
TextData: This is test number 5, which is plain text.
BinaryData:
```
示例2:`ShowMsgPartInfo()`
以下方法写入有关消息一部分的信息:
```java
ClassMethod ShowMsgPartInfo(msg as %Net.MailMessage, partno as %Integer)
{
Set part=msg.Parts.GetAt(partno)
Write "Message part details *****",!
Write "Message part: ", partno,!
Write "IsMultipart: ", part.IsMultiPart,!
Write "Number of parts: ", part.Parts.Count(),!
Write "Number of headers: ", part.Headers.Count(),!
Write "IsBinary: ", part.IsBinary,!
Write "IsHTML: ", part.IsHTML,!
Write "TextData: ", part.TextData.Read(),!
Write "BinaryData: ", part.BinaryData.Read(),!
}
```
这将产生与以下内容类似的输出(给定的消息与前面显示的不同):
```java
Message part details *****
Message part: 1
IsMultipart: 0
Number of parts: 0
Number of headers: 2
IsBinary: 0
IsHTML: 0
TextData: 1 test string
BinaryData:
```
示例3:`ShowMsgHeaders()`
下面的方法写入有关消息头的信息;可以编写一个类似的方法,对消息部分执行相同的操作。
```java
ClassMethod ShowMsgHeaders(msg as %Net.MailMessage)
{
Set headers=msg.Headers
Write "Number of headers: ", headers.Count(),!
//iterate through the headers
Set key=""
For {
Set value=headers.GetNext(.key)
Quit:key=""
Write "Header:",key,!
Write "Value: ",value,!!
}
}
```
这将产生类似于以下内容的输出:
```java
Number of headers: 16
Header: content-class
Value: urn:content-classes:message
Header: content-type
Value: multipart/alternative; boundary="----_=_NextPart_001_01C8286D.D9A7F3B1"
Header: date
Value: Fri, 16 Nov 2007 11:29:24 -0500
Header: from
Value: "XXX XXX"
Header: message-id
Value:
Header: mime-version
Value: 1.0
...
```
# 自动编码和字符翻译
电子邮件部分包含有关使用的字符集和使用的内容传输编码(如果有的话)的信息。作为参考,本节介绍如何使用此信息。
## 外发电子邮件
`%Net.SMTP`检查每个部分的字符集属性,然后应用适当的转换表。
如果未指定给定部件的字符集属性,InterSystems IRIS将使用UTF-8。
`%Net.SMTP`还检查`ContentTransferEncoding`属性。如果此属性为 `"base64"`或`"quoted-printable"`,则在创建消息时,`%Net.SMTP`会根据需要对正文进行编码。(如果内容传输编码为 `"7bit"` 或 `"7bit"`,则不需要编码。)
重要提示:请注意,如果内容为`“Base64”`编码,则不能包含任何`Unicode`字符。如果要发送的内容包括`Unicode`字符,请确保使用`$ZCONVERT`将内容转换为UTF-8。
## 传入电子邮件
`%Net.POP3`检查每个邮件部分的`Content-Transfer-Encoding`标头,并根据需要对正文进行解码。
然后`%Net.POP3`检查每个邮件部分的`Content-Type`标头。这会影响消息部分的字符集属性,还会控制在InterSystems IRIS中创建消息部分时使用的转换表。
问题
kun an · 五月 27, 2021
按照此网址的指示 https://gettingstarted.intersystems.com/language-quickstarts/java-quickstart/ 下载quickstarts-java示例代码 运行xepplaystocktsTask1模块程序提示InterSystems XEP is not supported by the specified server 请问有人知道具体原因吗我的server有什么不对吗。
使用客户端的server manager添加server没有server类型的选项,是因为我使用的cache版本目前不支持吗 不知您测试使用的具体是IRIS哪个版本,以及运行在哪个操作系统上。
还有提到的客户端使用的是哪个IRIS版本。低版本的客户端没法连上高版本的IRIS服务端,Caché客户端更加连不上IRIS的服务器。 您好 感谢解答。我使用的是IRISHealth_Community-2020.1.0.217.1-win_x64 运行在windows10上。我在官网教程上下载的示例代码,其余访问方式都运行正常就xep方式报错, 提示指定的server不支持, 不知道都有什么类型的server,哪些server可以支持 请参考下面资料检查是否符合运行需求以及相关配置是否正确:https://docs.intersystems.com/irisforhealth20201/csp/docbook/Doc.View.cls?KEY=BJAVXEP_intro#BJAVXEP_intro_config
其中的检查包括JDK版本、安装时的选项、服务%Service_CallIn是否打开以及环境变量CLASSPATH 的设置
文章
Michael Lei · 五月 26, 2021
https://www.intersystems.com/isc-resources/wp-content/uploads/sites/24/InterSystems-IRIS%E6%95%B0%E6%8D%AE%E5%B9%B3%E5%8F%B0%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97-20200531.pdf 怎么访问不了呢,404 最新版安装指南请参考:Linux 系统IRIS安装总结 谢谢,我问下有虚拟机分区的部分,应该怎么分区呢 看您是什么操作系统,Linux的话可以用fdisk命令进行分区。
文章
Michael Lei · 五月 24, 2021
作为一个软件架构师,如果要设计一个企业级的架构来满足当前的业务需求时,你需要达到5级的水平,这是一个巨大的挑战。有了InterSystems IRIS。这是有可能的。通过1个产品,你可以得到SQL + NoSQL + ESB + BI + Open Analytics + Real Time Virtual cubes + NLP + AutoML + ML(使用Python)和高级云支持 + Sharding支持。
以Oracle为例,你需要Oracle数据库+ Oracle NoSQL+ Oracle BI+ Oracle SOA套件+一些附加组件,如R、Partitioning和RAC以及一些Oracle云产品的NLP和AI功能。对于开源架构、IBM或者其他友商来说,也是类似的,你需要的组件只可能更多。
医疗机构在数字化转型在技术上最大的挑战之一,就是技术栈过于丰富、快速变化以及对人的技术要求很高(这也是为什么全栈工程师最值钱的原因);一个统一、高效、稳定、现代化、专为医疗定制的一体化数据平台能帮助客户很好地解决这个问题。IRIS for Health 是您的不二选择。
文章
姚 鑫 · 五月 24, 2021
# 第五章 向邮件添加附件
# 向邮件添加附件
可以将附件添加到电子邮件或消息部分(具体地说,是添加到`%Net.MailMessagePart`或`%Net.MailMessage`的实例)。要执行此操作,请使用以下方法:
这些方法中的每一种都会将附件添加到原始邮件(或邮件部分)的`Parts`数组中,并自动将`IsMultiPart`属性设置为1。
### AttachFile()
```java
method AttachFile(Dir As %String,
File As %String,
isBinary As %Boolean = 1,
charset As %String = "",
ByRef count As %Integer) as %Status
```
将给定文件附加到电子邮件。默认情况下,文件以二进制附件的形式发送,但您可以将其指定为文本。如果文件是文本,还可以指定该文件使用的字符集。
具体地说,此方法创建`%Net.MailMessagePart`的实例,并根据需要将文件内容放在`BinaryData`或`TextData`属性中,并根据需要设置`CharSet`属性和`TextData.TranslateTable`属性。该方法通过引用返回一个整数,该整数指示此新消息部分在部件数组中的位置。
此方法还设置消息或消息部分的`Dir`和`FileName`属性。
### AttachStream()
```java
method AttachStream(stream As %Stream.Object,
Filename As %String,
isBinary As %Boolean = 1,
charset As %String = "",
ByRef count As %Integer) as %Status
```
将给定流附加到电子邮件。如果指定了`Filename`,则附件被视为文件附件。否则,它将被视为内联附件。
### AttachNewMessage()
```java
method AttachNewMessage() as %Net.MailMessagePart
```
创建`%Net.MailMessage`的新实例,将其添加到消息中,并返回新修改的父消息或消息部分。
```
AttachEmail()
```
给定一封电子邮件(`%Net.MailMessage`的实例),此方法会将其添加到邮件中。此方法还设置消息或消息部分的`Dir`和`FileName`属性。
注意:此方法将`contentType`设置为`"message/rfc822"`。在这种情况下,不能添加任何其他附件。
示例:`MessageWithAttach()`
以下示例生成一封带有一个硬编码附件的简单电子邮件。它不为邮件提供任何地址;可以在实际发送邮件时提供该信息
```java
/// w ##class(PHA.TEST.HTTP).MessageWithAttachment()
ClassMethod MessageWithAttachment() As %Net.MailMessage
{
Set msg = ##class(%Net.MailMessage).%New()
Set msg.Subject="Message with attachment "_$h
Set msg.IsBinary=0
Set msg.IsHTML=0
Do msg.TextData.Write("This is the main message body.")
//add an attachment
Set status=msg.AttachFile("E:\", "HttpDemo.pdf")
If $$$ISERR(status) {
Do $System.Status.DisplayError(status)
Quit $$$NULLOREF
}
b
Quit msg
}
```
# 使用SMTP服务器发送电子邮件
如果有权访问SMTP服务器,则可以发送电子邮件。SMTP服务器必须正在运行,并且必须具有使用它所需的权限。要发送电子邮件,请执行以下操作:
1. 创建`%Net.SMTP`实例并根据需要设置其属性,特别是以下属性:
- `Smtpserver`是正在使用的`SMTP`服务器的名称。
- 端口是在`SMTP`服务器上使用的端口;默认值为25。
- 时区指定RFC 822指定的服务器时区,例如 `"EST"` 或 `"-0400"` 或 `"LOCAL"`。如果未设置,消息将使用世界时。
此对象描述将使用的`SMTP`服务器。
2. 如果`SMTP`服务器需要身份验证,请指定必要的凭据。为此:
a. 创建`%Net.Authenticator`的实例。
b. 设置此对象的用户名和密码属性。
c. 将`%Net.SMTP`实例的验证器属性设置为等于此对象。
d. 如果邮件本身具有授权发件人,请设置`%Net.SMTP`实例的`AuthFrom`属性。
3. 要使用到`SMTP`服务器的`SSL/TLS`连接,请执行以下操作:
a. 将`SSLConfiguration`属性设置为要使用的已激活`SSL/TLS`配置的名称。
`SSL/TLS`配置包括一个名为`Configuration Name`的选项,该选项是在此设置中使用的字符串。
b. 将`UseSTARTTLS`属性设置为0或1。
在大多数情况下,使用值0。如果服务器交互在普通`TCP`套接字上开始,然后在与普通套接字相同的端口上切换到`TLS`,则使用值1。
或者,将`SSLCheckServerIdentity`属性设置为1。如果要验证证书中的主机服务器名称,请执行此操作。
4. 创建要发送的电子邮件(如“创建单部分电子邮件”和“创建多部分电子邮件”中所述)。
5. 调用`SMTP`实例的`send()`方法。此方法返回一个状态,应该检查该状态。
6. 如果返回的状态指示错误,请检查`Error`属性,该属性包含错误消息本身。
7. 检查`FailedSend`属性,该属性包含发送操作失败的电子邮件地址列表。
以下各节中的示例使用了两种不同的免费SMTP服务,这些服务在编写本手册时是可用的。选择这些服务并不意味着特别认可。还要注意的是,这些示例并没有显示实际的密码。
`Samples`命名空间中还有其他示例。要查找它们,请在该命名空间中搜索`%Net.SMTP`。
重要提示:`%Net.SMTP`将邮件正文写入临时文件流。默认情况下,该文件被写入命名空间目录,如果该目录需要特殊的写入权限,则不会创建该文件,并且您会得到一个空的消息正文。
可以为这些临时文件定义新路径,并选择不限制写访问的路径(例如,`/tmp`)。为此,请设置全局节点`%SYS("StreamLocation",namespace)`,其中`NAMESPACE`是运行代码的名称空间。例如:
```
Set ^%SYS("StreamLocation","SAMPLES")="/tmp"
```
如果`%SYS("StreamLocation",namespace)`为`NULL`,则InterSystems IRIS使用`%SYS("TempDir",namespace)`指定的目录。如果未设置`%SYS("TempDir",namespace)`,则IRIS使用 `%SYS("TempDir")`指定的目录
示例1:`HotPOPAsSMTP()`和`SendSimpleMessage()`
此示例由一起使用的两个方法组成。第一个创建`%Net.SMTP`的实例,该实例使用已在`HotPOP SMTP`服务器上设置的测试帐户:
```java
/// w ##class(PHA.TEST.HTTP).HotPOPAsSMTP()
ClassMethod HotPOPAsSMTP() As %Net.SMTP
{
Set server=##class(%Net.SMTP).%New()
Set server.smtpserver="smtp.hotpop.com"
//HotPOP SMTP服务器使用默认端口(25)
Set server.port=25
//创建对象以进行身份验证
Set auth=##class(%Net.Authenticator).%New()
Set auth.UserName="isctest@hotpop.com"
Set auth.Password="123pass"
Set server.authenticator=auth
Set server.AuthFrom=auth.UserName
b
Quit server
}
```
下一个方法使用提供的SMTP服务器作为参数发送一条简单、唯一的消息:
```java
ClassMethod SendSimpleMessage(server As %Net.SMTP) As %List
{
Set msg = ##class(%Net.MailMessage).%New()
Set From=server.authenticator.UserName
Set:From="" From="xxx@xxx.com"
Set msg.From = From
Do msg.To.Insert("xxx@xxx.com")
//Do msg.Cc.Insert("yyy@yyy.com")
//Do msg.Bcc.Insert("zzz@zzz.com")
Set msg.Subject="Unique subject line here "_$H
Set msg.IsBinary=0
Set msg.IsHTML=0
Do msg.TextData.Write("This is the message.")
Set status=server.Send(msg)
If $$$ISERR(status) {
Do $System.Status.DisplayError(status)
Write server.Error
Quit ""
}
Quit server.FailedSend
}
```
示例2:`YPOPsAsSMTP()`
此示例创建使用`YPOPS`的`%Net.SMTP`实例的实例,`YPOPS`是一种客户端软件,提供对`Yahoo`电子邮件帐户的`SMTP`和`POP3`访问。它使用已为此目的设置的测试帐户:
```java
ClassMethod YPOPsAsSMTP() As %Net.SMTP
{
Set server=##class(%Net.SMTP).%New()
//local host acts as the server
Set server.smtpserver="127.0.0.1"
//YPOPs uses default port, apparently
Set server.port=25
//Create object to carry authentication
Set auth=##class(%Net.Authenticator).%New()
//YPOPs works with a Yahoo email account
Set auth.UserName="isc.test@yahoo.com"
Set auth.Password="123pass"
Set server.authenticator=auth
Set server.AuthFrom=auth.UserName
Quit server
}
```
可以将其与上例中所示的`SendSimpleMessage`方法一起使用。
示例3:`SendMessage()`
以下更灵活的方法同时接受`SMTP`服务器和电子邮件。电子邮件应已包含主题行(如果`SMTP`服务器要求),但不必包含地址。然后,此方法将电子邮件发送到一组硬编码的测试目的地:
```java
ClassMethod SendMessage(server As %Net.SMTP, msg As %Net.MailMessage) As %Status
{
Set From=server.authenticator.UserName
//make sure From: user is same as used in authentication
Set msg.From = From
//finish addressing the message
Do msg.To.Insert("xxx@xxx.com")
//send the message to various test email addresses
Do msg.To.Insert("isctest@hotpop.com")
Do msg.To.Insert("isc_test@hotmail.com")
Do msg.To.Insert("isctest001@gmail.com")
Do msg.To.Insert("isc.test@yahoo.com")
Set status=server.Send(msg)
If $$$ISERR(status) {
Do $System.Status.DisplayError(status)
Write server.Error
Quit $$$ERROR($$$GeneralError,"Failed to send message")
}
Quit $$$OK
}
```
## `%Net.SMTP`的其他属性
`%Net.SMTP`类还具有一些您可能需要的其他属性,具体取决于使用的SMTP服务器:
- `AllowHeaderEncoding`指定`Send()`方法是否对非`ASCII`标头文本进行编码。默认值为1,这意味着非`ASCII`标头文本按照RFC 2047指定的方式进行编码。
- `ContinueAfterBadSend`指定在检测到失败的电子邮件地址后是否继续尝试发送邮件。如果`ContinueAfterBadSend`为1,系统会将失败的电子邮件地址添加到`FailedSend`属性的列表中。默认值为0。
- `ShowBcc`指定是否将密件抄送标头写入电子邮件。这些通常会被SMTP服务器过滤掉。
文章
Michael Lei · 五月 24, 2021
本帖的目的是回答一个问题。 在本系列的第二篇帖子中,我包括了从 pButtons 提取的性能数据的图表。 有人在线下问我,有没有比剪切/粘贴更快的方法从 pButtons .html文件中提取 `mgstat` 等指标,以便在 Excel 中绘图。
参见:- [第 2 部分 - 研究收集的指标](https://cn.community.intersystems.com/post/intersystems-数据平台和性能-–-第-2篇)
pButtons 将其收集的数据编译成一个 html 文件,以便发送给 WRC 和查看整理的数据。 不过,尤其是对于长时间(如 24 小时)进行收集的 pButtons 来说,一些基于时间的数据(如 mgstat、vmstat 等)以图形方式查看更容易查找趋势或模式。
我知道把 pButtons 数据压缩到一个 html 文件再花时间去解压听起来很疯狂,但请记住,pButtons 是 WRC 用来获取许多系统指标的视图以帮助解决性能问题的工具。 系统级指标和 Caché 指标可以单独运行,但对我来说,在这个系列中使用 pButtons 捕获和分析性能指标是很方便的,因为我知道所有 Caché 安装都会有一个副本,或者可以下载副本,而且所有基本指标都可以放在一个文件中供不同的操作系统使用。 能够每天通过一个简单的例程来捕获这些指标也是很方便的,前提是没有以任何其他方式收集数据。
> _**2017 年 2 月。 我用 Python 重写了本文中的脚本,并添加了包括交互式 html 在内的图表。**_我认为 Python 实用工具有用得多。 请参见 [Yape - 另一个 pButtons 提取程序(以及自动创建图表)](https://community.intersystems.com/post/yape-yet-another-pbuttons-extractor-and-automatically-create-charts)
## 将 pButtons 性能指标提取到 csv 文件
由于我使用 Apple 笔记本电脑和 Unix 操作系统,所以很自然地写了一个快速 shell 脚本来提取数据到 csv 文件。 以下脚本从 pButtons .html 文件中提取 mgstat、vmstat 或 Windows 性能监视器数据。 下面的示例使用了大多数 *nix 系统都已安装的 Perl,但也可以使用其他脚本语言或在 Windows 上使用 powershell。
我将展示如何进行提取,有了这些信息,您就可以使用您喜欢的工具来执行同样操作。 关键是 html 文件中有标记来分隔指标。 例如,mgstat 用括号括起:
和
在 mgstat 部分中还有一些其他描述符信息,后面是 mgstat 输出的标题行。 vmstat 和 win_perfmon 的标记类似。
这个简单的脚本只是查找开始标记,然后输出从标题行到结束标记之前的行的所有内容。
#!/usr/bin/perl
# extract_pButtons.pl - Simple extractor for pButtons
# usage: ./extract_pButtons.pl
# pButtons has the following markers in the html source
# Metrics Parameters to pass
# -------- -------------------
# mgstat mgstat Date
# windows performance monitor win_perfmon Time
# vmstat vmstat fre
# usage example - Search for mgstat and redirect to .csv file
# ./extract_pButtons.pl DB1_20160211_0001_24Hour_5Sec.html mgstat Date > myMgstatOutput.csv
# usage example - Process a set of html files
# for i in $(ls *.html); do ./extract_pButtons.pl ${i} vmstat fre > ${i}.vmstat.csv ; done
# usage example - Pipeline to add commas
# ./extract_pButtons.pl P570A_CACHE_20150418_0030_day.html vmstat fre | ./make_csv.pl >P570A_CACHE_20150418_0030_day.html.vmstat.csv
$filename=$ARGV[0];
$string=$ARGV[1];
$firstLine=$ARGV[2];
$searchBeg="beg_".$string;
$search2=$firstLine;
$foundEnd="end_".$string;
$foundString=0;
$printIt=0;
$break=0;
open HTMLFILEIN, "
文章
Michael Lei · 五月 24, 2021
我本人和其他技术架构师经常需要向客户和供应商说明 Caché IO 要求以及 Caché 应用程序使用存储系统的方式。 在向客户和供应商说明典型的 Caché IO 配置文件和事务性数据库应用程序的要求时,下面的表格很有用。 原始表格由 Mark Bolinsky 创建。
在以后的帖子中,我将讨论更多关于存储 IO 的内容,所以现在贴上这些表格也作为将来文章的参考。
* * *
[本系列其他帖子的列表](https://cn.community.intersystems.com/post/intersystems-数据平台的容量规划和性能系列文章)
* * *
拥有设置良好的存储(如存储阵列)以提供可预测的磁盘 IO 性能,支持高可用性功能并为应用程序提供存储冗余、可伸缩性和可靠性,这几点至关重要。
## Caché 存储 IO 配置文件
根据所选的存储阵列技术,物理层的磁盘存储可分为池或磁盘组。 如果可能,出于可用性和性能考虑,应根据预期的 IO 配置文件对存储进行分区。 例如,数据和日志(事务日志)应该在不同的物理磁盘组上,因为它们有不同的 IO 配置文件,这也是出于可用性考虑,因为数据磁盘组中的损坏可以通过与损坏隔离的单独磁盘组中的日志来恢复。
同样,备份应该在单独的磁盘组中。 存储配置有多种选择,具体取决于操作系统、存储供应商和阵列型号。 具体要求因应用程序而异,需要特别注意物理和逻辑配置,包括物理和逻辑组或池的分配、RAID 类型、文件系统类型和并发性、分配的 GB 空间等。
下表详细介绍了 Caché 的读写 IO 配置文件:

## Caché 存储 IO 要求
我发现存储瓶颈是影响数据库系统性能的最常见问题之一。 一个常见的问题是只针对 GB 容量来调整存储大小,而不是分配足够多的独立磁盘来支持预期的每秒输入/输出操作数 (IOPS)。 尽管 SSD 和分层存储现在更加常见,但必须小心以确保 IOPS 可用。
为了保证可被最终用户接受的响应时间,需要具有最低 IO 性能配置文件的磁盘阵列。 根据是否使用单独的应用程序 (ECP) 服务器,要求会略有不同。 下表详细说明了预期的存储响应时间和关于 IO 配置文件的备注。

## 缺少了什么?
在与供应商交谈之前,您需要估计您的应用程序预期将驱动的 IOPS ,以便配置存储选项以满足上述要求。 本系列的第 1 和第 2 部分给出了如何收集指标的示例。
文章
Michael Lei · 五月 24, 2021
。之前我展示了如何运行 pButtons 来收集我们在下列帖子中研究的性能指标。
- [第 1 部分 - 入门:收集指标。](https://cn.community.intersystems.com/post/intersystems-数据平台和性能-–-第-1-篇)
- [第 2 部分 - 研究收集的指标。](https://cn.community.intersystems.com/post/intersystems-数据平台和性能-–-第-2篇)
## 更新:2020 年 5 月。
_自四年前写下本帖以来,我们已从 Caché 迁移到 IRIS。 有关 pButton (Caché) 和 SystemPerformance (IRIS) 文档的更新链接,请参见评论。 另请注意如何将系统更新到最新版本的性能工具。_
pButtons 与 Caché 5 及更高版本兼容,并已包含在最近的 InterSystems 数据平台分发版(HealthShare、Ensemble 和 Caché)中。 本帖旨在提醒您下载并安装最新版的 pButttons。
最新版本始终可以通过 ftp 下载。
ftp.intersystems.com/pub/performance
您需要下载以下文件:
pButtons_package.zip
解压 .zip 文件后,请查看 `readme.txt` 文件,以确保为您的 Caché 版本安装正确的文件。
要检查您现在已安装哪个版本,可以运行:
%SYS>write $$version^pButtons()
备注 1:
- 当前版本的 pButtons 需要一个许可证单元才能运行,将来的发行版将满足此要求。
- 此 pButtons 发行版的版本已更改。 — 之前的 pButtons 版本为 1.16c — 新发行版为版本 5。
备注 2:
- pButtons 版本 5 还更正了版本 1.16a 引入的一个问题,该问题可能导致收集时间非常长。 版本 1.16a 包含在 Caché 2015.1.0 中。 如果您有 pButtons 版本 1.16a 至 1.16c,则应该从 ftp 站点下载 pButtons 版本 5。
有关 pButtons 的更多详细信息,请参见下载的文件以及在线 Caché 文档。
文章
Michael Lei · 五月 24, 2021
您的应用程序已部署,一切运行正常。 很好,击个掌! 然后电话突然响个不停 – 用户投诉应用程序有时很“慢”。 这是什么意思? 有时? 您有哪些工具,查找和解决这个缓慢问题应查看哪些统计数据? 您的系统基础架构是否能承担用户负载的任务? 在投入生产之前,应该询问哪些基础架构设计问题? 如何自信地为新硬件规划容量,而不会过度规定? 如何停止电话铃声? 如何一开始就不让它响?
* * *
[本系列其他帖子的列表](https://cn.community.intersystems.com/post/intersystems-数据平台的容量规划和性能系列文章)
* * *
## 这将是一次旅程
这是本系列的第一个帖子,本系列将探讨可用于对系统性能进行监视、审查和故障排除的工具和指标,以及影响性能的系统和架构设计注意事项。 在旅程中,我们将朝多个方向前进,了解 Caché、操作系统、硬件、虚拟化以及根据评论中的反馈变为热门的其他方面的性能。
我们将关注反馈循环,其中性能数据提供了一个视角,通过它可查看已部署的应用程序和基础架构的优势和局限性,然后形成反馈以实现更好的设计和容量计划。
不言而喻,您应该不断检查性能指标,但不幸的是,如果客户只是查看数据,他们会多次对长期可见的性能问题感到惊讶。 但问题当然是 - 什么数据? 我们将从收集一些基本的 Caché 和系统指标来开始这一旅程,这样我们可以对您的系统当前的运行状况有一个感觉。 在以后的帖子中,我们将深入了解主要指标的含义。
有多个可用于系统监视的选项 – 来自 Caché 内部和外部,我们将在本系列中探讨其中的许多选项。
首先,我们将了解我最喜欢的用于连续收集数据的必备工具 ^pButtons,它已经安装在每个 Caché 系统上。
为确保您拥有最新的 pButtons 副本,请查看以下帖子:
## 收集系统性能指标 - ^pButtons
Caché 的 pButtons 实用工具可根据其创建的日志文件生成可读的 HTML 性能报告。 pButtons 输出的性能指标可以被轻松提取、绘图和审核。
pButtons html 文件中收集的数据包括:
* Caché 设置:配置、驱动器映射等。
* mgstat:Caché 性能指标 - 大多数的值是每秒平均数。
* Unix:vmstat 和 iostat:操作系统资源和性能指标。
* Windows:性能监视器:Windows 资源和性能指标。
* 其他有用的指标。
pButtons 数据收集对系统性能的影响非常小,这些指标已经由系统收集,pButtons 只是将它们打包以便归档和传输。
要保存基准以进行趋势分析和故障排除,好的做法是在一个完整的业务周期内每天收集 24 小时 pButtons(午夜到午夜)。 一个业务周期可能是一个月或更长时间,例如,从月末处理中捕获数据。 如果没有任何其他外部性能监视或收集,则可以全年运行 pButtons。
应注意以下关键点:
* 将日志目录更改为远离生产数据的位置,以存储累积的输出文件,避免出现磁盘满的问题!
* 定期运行操作系统脚本或以其他方式压缩和存档 pButtons 文件,这在 Windows 上尤其重要,因为文件可能很大。
* 定期审核数据!
如果出现需要立即分析的问题,可以预览(立即收集)pButtons 数据,同时继续存储指标,以便在当天运行结束时进行收集。
有关 pButtons 的更多信息(包括预览、停止运行和添加自定义数据收集),请参见最新的 Caché 文档中的 _Caché 监视指南_:
http://docs.intersystems.com
可以将 pButtons HTML 文件数据分离并提取(例如提取为 CSV 文件),以通过脚本或简单的剪切和粘贴将其处理成图形或进行其他分析。 我们以后将在下一个帖子中看到图表输出的例子。
当然,如果您有紧急的性能问题,请联系 WRC。
### 计划 24 小时 pButtons 数据收集
^pButtons 可以手动从终端提示符启动,也可以按计划启动。 要计划每天 24 小时收集:
1. 启动 Caché 终端,切换到 %SYS 命名空间,然后手动运行一次 pButtons 以设置 pButtons 文件结构:
%SYS>d ^pButtons Current log directory: /db/backup/benchout/pButtonsOut/ Available profiles: 1 12hours - 12 hour run sampling every 10 seconds 2 24hours - 24 hour run sampling every 10 seconds 3 30mins - 30 minute run sampling every 1 second 4 4hours - 4 hour run sampling every 5 seconds 5 8hours - 8 hour run sampling every 10 seconds 6 test - A 5 minute TEST run sampling every 30 seconds
选择选项 6 test - 5 minute TEST run sampling every 30 seconds。 请注意,您的编号可能有所不同,但 test 应该是显而易见的。
在运行期间,运行 Collect^pButtons(如下所示),您将看到包括 runid 在内的信息。 在此例中为“20160303\_1851\_test”。
%SYS>d Collect^pButtons
Current Performance runs:
<strong>20160303_1851_test</strong> ready in 6 minutes 48 seconds nothing available to collect at the moment.
%SYS>
注意到这个 5 分钟运行还剩 6 分 48 秒吗? pButtons 为所有运行增加了 2 分钟宽限期,以便有时间将日志收集和整理成 html 格式。
2. 重要!更改 pButtons 日志输出目录 – 默认的输出位置为 <缓存安装路径>/mgr 文件夹。 例如,在 unix 上,日志目录的路径可能如下所示:
do setlogdir^pButtons("/somewhere_with_lots_of_space/perflogs/")
确保 Caché 有该目录的写权限,并且有足够的磁盘空间用于累积输出文件。
3. 运行以下命令以创建一个新的 24 小时配置文件,间隔为 30 秒:
write $$addprofile^pButtons("<strong>My_24hours_30sec</strong>","24 hours 30 sec interval",30,2880)
检查该配置文件是否已添加到 pButtons:
%SYS>d ^pButtons
Current log directory: /db/backup/benchout/pButtonsOut/
Available profiles:
1 12hours - 12 hour run sampling every 10 seconds
2 24hours - 24 hour run sampling every 10 seconds
3 30mins - 30 minute run sampling every 1 second
4 4hours - 4 hour run sampling every 5 seconds
5 8hours - 8 hour run sampling every 10 seconds
6 My_24hours_30sec- 24 hours 30 sec interval
7 test - A 5 minute TEST run sampling every 30 seconds
select profile number to run:
注意:您可以更改收集间隔 – 30 秒对于例行监视是可以的。 对于例行 24 小时运行,我不会选择低于 5 秒的间隔 (…”,5,17280),因为 pButtons 在每个间隔都会收集数据,而导致输出文件变得非常大。 如果您要对一天中的某个特定时间进行故障排除,并需要更细化的数据,请使用默认的配置文件之一,或创建一个新的自定义配置文件,取较短的时间段,例如 1 小时,间隔为 5 秒 (...",5,720)。 多个 pButtons 可以同时运行,因此可以同时运行一个间隔为 5 秒的短 pButtons 和一个 24 小时 pButtons。
4. 提示 对于 UNIX 站点,可审查磁盘命令。 “iostat”命令使用的默认参数可能未包括磁盘响应时间。 首先显示当前配置了哪些磁盘命令:
%SYS>zw ^pButtons("cmds","disk")
^pButtons("cmds","disk")=2
^pButtons("cmds","disk",1)=$lb("iostat","iostat ","interval"," ","count"," > ")
^pButtons("cmds","disk",2)=$lb("sar -d","sar -d ","interval"," ","count"," > ")
要收集磁盘统计数据,请使用适合您的 UNIX 安装版的命令来编辑语法。 注意尾部空格。 以下是一些示例:
LINUX: set $li(^pButtons("cmds","disk",1),2)="iostat -xt "
AIX: set $li(^pButtons("cmds","disk",1),2)="iostat -sadD "
VxFS: set ^pButtons("cmds","disk",3)=$lb("vxstat","vxstat -g DISKGROUP -i ","interval"," -c ","count"," > ")
您可以同时运行 iostat 和 sar 命令来创建非常大的 pButtons html 文件。 对于定期的性能审查,我通常只使用 iostat。 要仅配置一个命令:
set ^pButtons("cmds","disk")=1
有关配置 pButtons 的更多详细信息,请参见在线文档。
5. 在 Management Portal > System Operation > Task Manager 中安排 pButtons 在午夜启动:
Namespace: %SYS
Task Type: RunLegacyTask
ExecuteCode: Do run^pButtons("My_24hours_30sec")
Task Priority: Normal
User: superuser
How often: Once daily at 00:00:01
### 收集 pButtons 数据
最新版的 InterSystems 数据平台中随附的 pButtons 包括自动收集功能。 要手动收集数据并整理成一个 html 文件,请在 %SYS 命名空间中运行以下命令以生成未完成的 pButtons html 输出文件:
do Collect^pButtons
该 html 文件将位于您在步骤 2 设置的日志目录中(如果您未设置,就**现在去设置!**)。 否则默认位置为 <Caché 安装目录/mgr>
文件将命名为 <主机名\_实例\_名称\_日期\_时间\_配置文件名.html>,例如 vsan-tc-db1\_H2015\_20160218\_0255_test.html
### Windows 性能监视器注意事项
如果操作系统是 Windows,则可以使用 Windows 性能监视器 (perfmon) 收集数据,与所收集的其他指标同步。 在 pButtons 的旧版 Caché 发行版中,需要手动配置 Windows perfmon。 如果帖子评论有需求,我将写一篇帖子介绍如何创建 perfmon 模板来定义要监视的性能计数器,并安排与 pButtons 相同的运行期间和间隔。
### 总结
我们从本帖开始收集一些要研究的数据。 在本周晚些时候,我将开始研究一些样本数据及其含义。 您可以使用您在自己的系统上收集的数据。 到时见。
公告
Claire Zheng · 五月 24, 2021
5月27日,CHIMA大讲堂第十九期邀请医院信息化专家和InterSystems技术专家,共同探讨集成平台赋能智慧医院建设这一话题。欢迎大家围观参会!InterSystems专家演讲概要如下:
演讲人
李岩 ( @Li.Yan ),InterSystems中国业务拓展经理演讲主题构建更智慧的医院信息平台演讲概要在需求的拉动下和政策、标准的推动下,为了给患者提供更好的就医体验,给医务人员提供更好的临床服务,给管理者提供更好参考和手段,智慧医院的建设如火如荼地发展起来了。智慧医院的建设并不是某一应用、某一系统的点状建设,而是打通各个环节、各个系统的全面的建设。
作为医院系统互通的核心的医院信息平台,如何更加“智慧”,如何更好地赋能智慧医院建设?希望本期分享能为您带来一些启发。
演讲人
乔鹏 (@Qiao.Peng) ,InterSystems中国技术总监演讲主题从集成平台到医院信息平台演讲概要当前医院信息化建设是否需要一个集成平台?是不是仅仅因为互联互通才需要集成平台?
集成平台是否只是一个过渡性的产品?医院信息平台是集成平台的发展方向吗?
此次分享将和大家一起讨论这些问题,探究集成平台出现的原因、它的价值和不足,以及目前医疗信息化建设对集成平台的挑战。探讨医院信息平台作为集成平台的未来,它的核心价值、能力、设计思路和实施路径。
完整日程如下:
手机端请扫描图片中二维码,电脑端请复制下方链接观看。https://djt.chima.org.cn/
欢迎大家报名、围观、参会!
陆主任会从目前平台建设存在的问题、平台框架选择、平台建设注意事项等全方位,多角度的介绍广医二院的医疗信息平台建设