搜索​​​​

清除过滤器
文章
Lilian Huang · 三月 30, 2022

[首次使用InterSystems IRIS] 互操作性: 一个Production是什么?

这篇文章是前面文章[首次使用InterSystems IRIS] 互操作性: 它是如何工作的?的延续。 在上一篇文章中,解释了互操作性菜单如何用于系统集成。 在本文中,我想解释如何用互操作菜单开发系统集成。 首先,您想创建什么样的业务流程? 请一边思考,一边开始以下内容。 Production(生产) 消息 组件 业务服务 业务流程 业务运营 Production被定义和用作指定系统集成所需的组件及存储组件的配置,这些配置通过管理门户界面使用(内部被存储为生产的类定义)。 例如,假设您正在创建一个业务服务,该服务定期处理放置在指定目录中的文件。 在这种情况下,有必要准确配置要监测的目录和要处理的文件。 一个生产就是预先准备好用于存储这些配置。 这些配置取决于发送和接收数据的组件所使用的适配器。 适配器是用于简化与外部系统连接的类,有些是协议特定的,如 Mail/File/SOAP/FTP/HTTP/SQL/TCP,有些是标准特定的,如 HL7。 有关适配器的更多信息,请参阅文档(protocol-specific adapters and adapters related to EDI documentation) 由于我们将必要的组件定义为Production,“启动Production”将启动系统集成,而“停止Production”将停止系统集成。 完成Production需要的开发是系统集成所需组件的创建,具体包括以下内容: • 信息 • 组件(业务服务、业务流程、业务运营) • 数据转换等。 上面的内容会在后面的文章中慢慢讲解。 首先,让我们使用Production示例来启动Production,并在检查配置的同时通过查询数据来检查消息处理的流程。 模版可以从这里下载https://github.com/Intersystems-jp/selflearning-interoperability。 如使用容器,请使用 git 克隆 下载示例代码,导航到克隆的目录,然后运行 docker-compose up -d 就这么简单! 请在此处参考流程here (创建容器需要一些时间)。 如果不使用容器,下载示例后新建一个命名空间,并将src文件夹下的所有类定义文件(extension .cls)导入创建的命名空间。 更多关于创建命名空间的过程,请参考本文this article.07:03之后的视频。 有关示例代码的更多详细信息,请参阅README。 准备就绪后,访问管理门户(更改 Web 服务器的端口号以匹配您的环境)。 http://localhost:52773/csp/sys/UtilHome.csp 进入管理门户 > 互操作性 > 配置 > 生产。 如果您使用的是容器以外的方法,请连接到您导入源代码的命名空间,访问[[配置] > [生产],,单击[打开] 按钮,选择[开始] > [生产],,然后单击 [开始] 按钮。 ※ 如果您使用容器以外的东西,则需要进行一些初始设置。 请在尝试以下内容之前设置以下描述的内容contents described below。 生产页面将为每一个 “服务”、“流程”和“操作”组件显示为[● 组件名称] ]。 单击组件名称可更改屏幕右侧“设置”选项卡的内容。 例如点击Start.GetKionOperation(单击),显示如下。 组件有[HTTP Server] 和 [URL] 配置来连接Web API. 配置底部有一个 [appid] 字段,您可以在其中输入您获得的 API 密钥。 [appid] 附近有一个 [lang] 字段,设置为“ja”(“ja”=日语)。 [lang] 设置来自 OpenWeather 的响应语言。 如用英语,设置为“en”。 完成设置这些配置后,单击“应用”按钮。 如果您使用的是容器,则该配置完成。 欲了解更多信息,请点击here。 如果您正在尝试容器以外的其他配置 请提前做好以下两项设置: 1) 配置SSL客户端。 由于要连接的 Web API 将使用 HTTPS 进行通信,因此请提前在 IRIS 端配置 SSL 客户端。 为了匹配生产模版的设置,我们将使用名称 [openweather]。 生产中的设置如下: 单击管理门户 > [系统管理] > [安全] > [SSL/TLS 配置] > [新建配置] 按钮,在“配置名称”字段中输入“openweather”,然后单击“保存”按钮 结束。 2) 为 REST 创建一个基本 URL 在示例制作中,为使能够通过 REST 输入信息,我们已经进行了配置,基本 的URL for REST配置需要在 IRIS 端。 在生产示例中,我们将配置 /启动设置为基本 的URL。 由于 Start.REST 类存在于导入示例的命名空间中,因此我们将指定该类作为调度类,并添加 %All 作为应用程序角色,以在访问时省去身份验证。 管理门户 > 系统管理 > 安全 > 应用程序 > Web 应用程序路径 > 单击“创建新的 Web 应用程序”按钮。 在名称字段中,指定 /start; 在命名空间字段中,指定从中导入样本的命名空间; 在 Dispatch Class 字段中,指定 Start.REST; 在允许的身份验证方法字段中,选择“未Unauthenticated”,然后保存文件。 保存后,将 %All 角色添加到“application role ”选项卡上的应用程序角色中。 尝试发送数据 全部配置好后,尝试用业务服务通过 REST 发送信息并让它运行。 http://localhost:52773/start/weather/Takoyaki/Osaka 上面的例子是假设某人在大阪购买了“章鱼烧”的 URL。 运行后画面如下。 检查已发送到生产的消息。 在管理门户 > 互操作性 > 配置 > 生产中,单击以下服务: 选择屏幕右侧的“消息”选项卡,然后单击标题字段列下方的任意数字。 如果您没有看到它,请重新加载您的浏览器。 使用 Visual Trace 页面,您可以看到组件之间发送和接收的消息信息。 您可以看到天气信息是从 Web API 检索并在浅蓝色框架中发送回来的。 通过这种方式,您可以使用跟踪来查看当时正在发送和接收哪些数据以及以什么顺序。 在整篇文章中,我们已经确认了Production已经定义了需要的组件和参考示例代码设置的系统集成 我们还确认,我们可以使用 Visual Trace 页面按时间顺序参考通过 Production 的消息。 在下一篇文章中,我们将讨论创建此跟踪中显示的“消息”背后的概念以及如何实际定义它。
文章
Lilian Huang · 三月 30, 2022

[首次使用InterSystems IRIS] 互操作性: 它是如何工作的?

这篇文章的目的是为了说明如何使用互操作菜单实现系统集成。 图片左侧窗口是接受外部系统发送信息的窗口。 信息接收方式种类很多,如定时监控指定目录来读取文件,定期查询数据库,输入且等待信息输出,或直接调用其他应用程序系统传送信息。 在系统集成配置中创建IRIS 互操作性菜单,接收到存储在一个对象中的信息被称为一条消息message(以下统称为消息)。消息被发送到组件component (以下统称为组件)中做后续处理。 使用所有接收到的信息或仅使用其中的一部分就能用来创建消息。 假设您要将信息中包含的消息发送给外部系统。这种情况下,需要将该消息发送给负责请求外网处理的组件(图右侧)。接收到消息的组件会请求外部系统对其进行处理。 此外,假设一条消息需要人工审查、数据转换或附加数据。这种情况下,消息会被发送到图表中间的业务流程管理组件(BPM),该组件负责协调处理业务流程。 消息用于在每个组件之间发送和接收数据。当发送或接收消息时,消息会被自动存储在数据库中。 由于消息存储在数据库中,因此在数据转换前后可以检查其差异性。在操作期间,或过程中间重新开始(重新发送),可以检查作为问题根源的消息。在开发、测试和操作的每个阶段可以验证正在使用的消息状态。 一个简单的系统集成图将分为三个部分(业务服务Business Service、业务流程Business Process和业务操作 Business Operation),如下图所示。 还有一个称为“生产Production”的定义,它存储有关要使用的组件信息(例如,连接信息)。 各组件功能如下: 业务服务Business Service 负责从外部源接收信息,创建消息,以及向其他组件发送消息。 业务流程Business Process 该功能在收到消息时被激活,并负责协调流程(按预先定义的顺序调用组件、等待响应、等待人工审核结果等)。 业务运营Business Operation 此功能在收到消息时被激活,会请求外部系统处理该消息。 消息是用于在组件之间发送和接收数据。 当收到一个消息时,业务服务以外的所有组件开启处理流程。 问题是,创建和使用此消息的目的是什么? 通过创建消息可获取中继到外部系统的数据并检索进入业务服务。 由于不是所有的外部系统都用相同类型的数据格式连接到 IRIS,并且要中继的内容各不相同,因此生产者可以根据信息自由定义消息类别。 有两种类型的消息:请求(= 请求消息)和响应(= 响应消息)。触发组件激活的消息被称为request(=请求消息),组件处理后响应的消息称为response(=响应消息)。 这些消息在考虑中继流程时会被设计。 在接下来的文章中,我们将使用一个案例来概述生产、消息和组件的创建。 上一篇链接,请参考:《首次使用InterSystems IRIS 》-让我们来使用互操作性!链接如下:https://cn.community.intersystems.com/post/%E3%80%8A%E9%A6%96%E6%AC%A1%E4%BD%BF%E7%94%A8intersystems-iris-%E3%80%8B-%E8%AE%A9%E6%88%91%E4%BB%AC%E6%9D%A5%E4%BD%BF%E7%94%A8%E4%BA%92%E6%93%8D%E4%BD%9C%E6%80%A7
公告
Claire Zheng · 六月 15, 2022

一起来录制InterSystems全球峰会的问候视频吧!

Hi 开发者们,你或许已经知道了,今年InterSystems全球峰会线下会议再次开启!我们非常期待能在现场见到诸位! 然而,并不是所有的开发者社区成员都有机会参加(我也是!)所以我们决定制作一个很酷的视频收集来自社区成员们问候🎥 无论身在何方,让我们一同以虚拟方式来参加这次伟大的盛会吧!🌏 ⬆️要求:您录制一句2-3秒的短视频,视频内容是向我们的社区成员说 “Hi From your country (来自XX的问候,英语视频最佳)”,然后将视频上传至 这里 ,这样,我们可以把来自各地的许多视频剪辑在一起,在2022年全球峰会上展示。您也可以通过开发者社区联系我,将视频直接分享给我。 截止日期:美东时间6月18日(周五) 期待见到你!
文章
Qiao Peng · 四月 14, 2022

InterSystems 数据平台与三级等保 - 第三篇

8. 应用安全 InterSystems数据平台上可能运行着多种应用,例如Web网页应用、SOAP服务、REST API、HL7 接口、SQL服务等等。这些应用种类繁多,面临的安全风险也是巨大的,例如代码注入攻击和HTTP的跨站请求伪造攻击等。 这其中代码注入攻击和针对Web应用的攻击尤其需要重视。 8.1 代码注入攻击 代码注入攻击通常和我们编写的程序相关,需要在程序编写时注意避免。 8.1.1 SQL注入攻击 SQL注入攻击是典型的代码注入攻击,通过从外部注入恶意SQL语句获得数据权限并获得敏感数据。关系型访问方式都是通过客户端SQL语句传入执行的,因此它是数据库重点需要防范的。 InterSystems数据平台并不支持以分号分割的多条SQL语句作为一个SQL命令执行,因此它本身免疫了主要的SQL注入攻击手段。 InterSystems数据平台支持动态SQL,即允许SQL命令作为方法的字符串参数传入,这会给SQL注入攻击留有隐患。在编程时,应避免开放服务用于接受完整的SQL语句作为参数,而是通过SQL动态传参来构建运行时SQL。 InterSystems数据平台支持行级安全,这有助于避免在SQL注入攻击时,将所有数据返回给攻击请求。 8.1.2 $ZF InterSystems数据平台提供了系统函数$ZF,用以调用外部命令。其中$ZF(-1)和$ZF(-2)用以调用服务器操作系统的命令。这可能会成为代码攻击的隐患。 在使用$ZF开发服务时,应避免把完整的操作系统命令作为字符串参数传入来执行,而应仅传入必要的数据,由服务器端方法来组成需要执行的操作系统命令,避免注入攻击。 8.2 Web应用安全管理 InterSystems数据平台提供多种Web应用,都是基于HTTP/HTTPS协议的,例如InterSystems数据平台的管理门户网页、用户自定义的网页、开放的SOAP服务、RESTful API。 既然走HTTP/HTTPS,所以首先应该部署专用Web服务器,并配置HTTPS来提供这些Web服务,在传输通道上保障安全。 除了传输通道,要得到更安全的生产环境,还有其它的安全设置需要检查和配置。 8.2.1 CSP/ZEN用户自定义网页应用 每个InterSystems数据平台等命名空间默认都有一个Web应用,可以通过它提供用户自定义网页应用。也可以创建一个新的Web应用提供用户自定义的网页应用。 第一个要检查的项目,是要看看这些默认创建的Web应用是否需要。如果不需要,应该禁用 – 取消选中“Enable Application”。 第二个要检查的项目,是这个Web应用使用的身份认证方式。在生产环境上,不应该使用“未验证”方式,所以应该取消选中该选项。 第三个要设置合适的“必要的资源”,它是对网页应用的资源权限要求。必须具有该资源的使用权限的用户,才能访问该网页应用。 第四个要决定是否开启防CSRF攻击,建议开启“Prevent Login CSRF attack”。 8.2.2管理门户 InterSystems数据平台的管理门户就是CSP/ZEN开发的网页应用,它具有大部分系统管理和监控能力,例如安全配置、高可用配置等。 除了8.2.1提到的对网页应用的安全配置项目之外,InterSystems数据平台预置了一系列系统角色和系统资源,用于让不同用户对管理门户的不同功能页面具有不同的权限。例如操作员角色(%Operator)不具有创建、修改用户的权限。 这些用户权限检查是通过配置给管理页面的系统资源来判断的,只有对这些页面系统资源有权限的用户才能访问该管理页面。 为了提供更细颗粒度的管理,除了配置给管理门户页面上的系统资源,用户可以将自定义资源加到管理门户页面上。这样,用户需要同时具有系统定义的页面资源权限和用户自定义资源权限才能访问和使用管理页面。 如何查看系统预置的管理页面资源和配置自定义资源?在每个管理门户页面菜单项上,都有链接,点击它就可以查看该管理页面分配的系统资源和自定义资源。如果要添加自定义资源,点击“分配”,就可以在弹出的页面中进行配置。 通过配置自定义资源,可以实现任意颗粒度的管理门户权限控制。 如果您在管理互操作产品,想了解系统提供的预定义安全资源,可以参考文档 8.2.3 SOAP服务 除了SQL服务,SOAP服务是InterSystems数据平台经常要开放的服务类型之一。如果您的生产环境上开放了SOAP服务,应该检查它的安全配置。 开启SOAP服务 InterSystems数据平台的SOAP服务也是通过Web应用开放的。默认情况下,Web应用是没有开放“入站Web服务”的,也就是说默认Web应用是不能提供SOAP服务的。如果需要开放SOAP服务,需要选中对应Web应用的“入站Web服务”。 注意:如何仅是查看WSDL,并不需要开启此选项。 开启SOAP服务测试页功能 InterSystems数据平台还提供SOAP服务测试页功能,该功能可以使用Web页面来测试SOAP服务,而不需要通过SOAPUI等工具。 为了安全,默认SOAP服务测试页功能是未开启的。如果需要开启,需要通过系统安全设置项开启: SET ^SYS("Security","CSP","AllowPrefix",<SOAP应用路径>,"%SOAP.")=1 注意: 1. <SOAP应用路径>最后需要加"/",例如 "/csp/user/" 2. 该设置项不影响SOAP服务,仅影响测试页 SOAP认证与权限 在生产环境上,不应该发布无需认证的SOAP服务。因此也需要取消选中“未验证”方式。 同时通过“必要的资源”设置,可以为SOAP服务指定需要的权限。 SOAP安全协议 另外,SOAP本身有很多安全协议,例如WS-Security, WS-Policy, WS-SecureConversation, WS-ReliableMessaging... 它们提供SOAP消息头及消息体加密、数字签名等机制保障SOAP服务安全。 InterSystems数据平台支持这些SOAP安全协议,可以通过这些协议加强SOAP服务的安全。 8.2.4 RESTful API RESTful API越来越多的用于轻量化的服务提供。与SOAP服务类似,InterSystems数据平台的RESTful API也是通过Web应用提供的。 因此上面介绍的Web服务的安全检查项也适用于RESTful API应用。 另外,如果部署了InterSystems API管理器,它本身也提供了安全相关的功能,例如用户认证、权限控制等。因此也要检查InterSystems API管理器的安全设置。 8.3 安全建议 不要拼接SQL语句,而是通过传参数构建运行时的SQL 避免使用动态SQL 启用行级安全 将$ZF调用封装在方法中,避免将操作系统命令通过字符串传入 部署独立的Web服务器,并启用HTTPS 禁用"未验证"的身份验证方式 选择"密码"或"Kerberos" 开启防跨站请求伪造(CSRF) 攻击 增加必要的资源权限要求 对"应用程序角色"配置合适的角色 为SOAP服务建立独立的Web应用,不使用命名空间默认的Web应用发布SOAP服务 不应该发布不需要用户认证的SOAP服务和RESTful API! 使用合适的认证策略,例如密码或用户名令牌 使用合适的SOAP安全协议,例如消息加密、数字签名 在部署了InterSystems API管理器时,通过它进一步约束安全选项 9. 安全审计 InterSystems数据平台提供审计能力,提供防篡改的审计数据库,用于记录审计事件。审计数据可以查看、搜索和导出。 通过管理门户 > 系统 > 安全管理 > 审计 可以开启和配置审计。 InterSystems数据平台预置了一系列系统审计事件,例如用户登录事件、登录失败事件等。并非所有的预置系统审计都默认开启,用户可以在系统审计事件配置页面进行配置,决定审计哪些系统事件。 除了系统预置的审计事件,InterSystems数据平台运行用户自定义审计事件,例如谁修改了特定的类。通过管理门户 > 系统 > 安全管理 > 用户定义的审计事件 可以创建自定义审计。 9.1 安全建议 开启审计 对重要的用户级事件建立自定义审计事件 定期分析审计的用户行为模型,识别发现异常请求 10. 备份与恢复 数据平台的备份与恢复是保障数据安全的另一项机制。定期的备份保障在意外发生时数据可以最大限度的恢复。例如是误删除了数据和代码,InterSystems数据平台的镜像高可用也无法恢复这些误删除的内容,因为误删除也会在备机上重做。这时,备份是唯一可以恢复误删除数据的希望。 所以应该有备份恢复的自动化策略,定期地执行备份,并将备份保存在与生产环境隔离的地点妥善保存。 InterSystems数据平台支持多种备份工具和备份策略。 备份工具: 冷备份 – 卸载数据库,拷贝数据库文件,加载数据库。冷备份需要计划宕机时间 联机热备份 – InterSystems数据平台提供的在线备份,无需计划宕机时间。数据规模很大时,备份时间较长 外部备份(快照备份) – 在线备份,无需计划宕机时间。通常速度很快,但需要外部备份工具 InterSystems数据平台使用内建的联机热备份工具时,支持这些备份策略: 全备份 – 备份全部数据 增量备份 – 备份上次备份之后修改的所有数据 补充备份 - 备份上次全备份之后修改的所有数据 可以使用这些备份方式,组合成一个自动的备份计划,例如:周日执行全备份、周一周二执行增量备份、周三执行补充备份、周四周五周六执行增量备份。 这些备份文件和备份之后的所有日志文件(Journal文件)和数据平台配置文件,以及项目相关的静态文件一起,例如网页文件,才是完整的生产环境备份集。完整的备份集才能保证恢复到指定的时间节点上。 有了备份并不是万无一失,需要验证备份是否可用。应该建立备份集恢复测试的环境,定期对备份集进行恢复测试,以确保备份集是可用的。 10.1 安全建议 建立自动的备份任务 备份应保存在独立的存储和隔离的物理位置 定期检查备份集的可用性 11. 正确安装InterSystems数据平台 在InterSystems数据平台安装时,会提示选择安全级别。因此在安装时,就应该选择正确的安全级别,避免后期大量的安全配置检查和调整。 InterSystems数据平台安装时会提供3个安全级别选择:Minimal、Normal和Locked Down。 Minimal:是针对于本机开发环境安装的安全级别、也是最低的安全级别,通常是被用于开发者在自己的笔记本电脑上安装InterSystems数据平台的开发实例。它几乎没有安全限制,例如允许无认证登录、匿名用户拥有%All的权限。因此绝不应该在生产环境上以此级别安装。如果您已经以Minimal安全级别安装了生产环境,那应该立刻修改安全配置。 Normal:是针对通常用途的安全级别,收紧了安全策略,可以作为大多数生产环境的初始安全配置。建议生产环境安装时,以此级别进行安装,并在安装之后按需调整安全配置。 Locked Down:是针对高安全需求的生产环境的安全级别。它禁用了多数服务、收紧了服务策略,因此安装后就已经提供了一个较为安全的实例。 Minimal Normal Locked Down 安全设置 密码模式 3.32ANP 3.32ANP 8.32ANP 不活动禁用天数* 0 90天 90天 启用_SYSTEM用户 是 是 否 分配给用户UnknownUser的角色 %All 无 无 服务策略 Use 权限为公共权限 是 是 否 需要认证 否 是 是 服务 %Service_Bindings 启用 启用 禁用 %Service_CacheDirect 启用 禁用 禁用 %Service_CallIn 启用 禁用 禁用 %Service_ComPort 禁用 禁用 禁用 %Service_Console* 启用 启用 启用 %Service_ECP 禁用 禁用 禁用 %Service_Monitor 禁用 禁用 禁用 %Service_Telnet* 禁用 禁用 禁用 %Service_Terminal† 启用 启用 启用 %Service_WebGateway 启用 启用 启用 12. InterSystems 数据平台的安全建议工具 InterSystems数据平台提供安全检查和建议工具。通过管理门户 >系统 > 安全管理 > 安全顾问 即可使用该工具。 安全建议工具会提示安全建议,点击“详细信息”链接,会自动跳到对应安全配置页面。在生产环境上线前,建议使用该工具进行检查。 13. InterSystems 数据平台三级等保检查清单 针对三级等保合规,检查清单如下: 1. 配置基于TLS的数据加密通道** 所有对InterSystems 数据平台的连接方式都配置使用加密通道 2. 部署独立的Web服务器 配置Web服务器应用HTTPS,并禁用不安全的 HTTP 方法 3. 服务配置 关闭不必要的服务 对必要开启的服务,选择安全的认证方式 禁用“未验证”方式 进一步限定允许接入的IP地址 4. 加强认证 系统级禁用 “无认证” 选用更安全的认证方式 5. 收紧授权** 数据库应该设置自己独立的资源,而非使用%DB_%DEFAULT 谨慎使用公共权限 创建自己需要保护的新资源** 6. 用户与角色 仅管理员有%All角色 要求用户账号更安全的密码模式 设置密码错误数次后停用账号 7. 数据安全 对敏感数据进行全数据库加密 合理的数据读写权限 必要时,添加行级和列级安全** 8. 应用安全 不要拼接SQL语句,而是通过传参数构建运行时的SQL** 避免使用动态SQL** 启用行级安全** 将$ZF调用封装在方法中,避免将操作系统命令通过字符串传入** 禁用不必要的Web应用 ** 对Web应用,禁用"未验证"的身份验证方式 对Web应用,开启防跨站请求伪造(CSRF) 攻击 对Web应用,对"应用程序角色"配置合适的角色,不应随意赋予%All ** 为SOAP服务建立独立的Web应用,不使用命名空间默认的Web应用发布SOAP服务 ** 不应该发布不需要用户认证的SOAP服务和REST API! 使用合适的SOAP安全策略,例如消息加密、数字签名 9. 审计 开启审计 对重要的用户级事件建立自定义审计事件 ** 定期分析审计的用户行为模型,识别发现异常请求 ** 10. 备份与恢复 建立自动的备份任务 备份应保存在独立的存储和隔离的物理位置 定期检查备份集的可用性 注:**项目不是三级等保的必查项,但建议进行检查和配置。
公告
jieliang liu · 四月 20, 2022

[视频]用InterSystems IRIS商业智能创建数据透视表

开发者们好, 我们在Bilibili的”InterSystems中国“频道 发布了新的视频! 了解如何使用InterSystems IRIS Business Intelligence的Analyzer工具来创建在仪表板上显示的透视表。本视频展示了Analyzer工具的中心组件,并演示了如何构建一个透视表。 请欣赏并继续关注! 这个有字幕了,赞👍
文章
Qiao Peng · 四月 11, 2022

InterSystems 数据平台与三级等保 - 第一篇

数据平台不仅要安全,还要合规,三级等保是我们要符合的主要安全规范。InterSystems的数据平台和集成平台产品都和三级等保有关。如果没有正确配置它们的安全选项,就会影响到整个系统的安全,影响到合规性。 在生产环境上,如何配置安全的InterSystems的数据平台,并达到三级等保的要求? 这个系列文章,针对InterSystems 数据平台的安全架构,围绕对三级等保的合规性展开,介绍如何配置出一个安全、合规的数据平台。 注:本文提到的InterSystems的数据平台,包括Caché数据库、Ensemble集成平台、HealthConnect医疗版集成平台和InterSystems IRIS数据平台。 三级等保的要求 三级等保要求 对数据平台的要求 身份鉴别 确保用户身份是真实、准确的 访问控制 控制:谁、以什么方式、从什么设备可以访问什么数据和功能? 入侵防范 防范静态数据、传输中的数据、日志和备份中的数据被入侵 恶意代码防范 防止恶意代码被植入和执行,例如SQL注入 可信验证 数据完整性 保证数据完整性和一致性的能力 数据备份恢复 对数据的备份与恢复能力和策略 InterSystems数据平台安全架构 InterSystems数据平台提供了一个完善的安全架构,用以保护从接入到数据保存的各个层面的数据安全: InterSystems数据平台提供丰富的安全相关特性,用以保障系统安全性和合规性: 我们按数据的流向逐一展开,看看应该如何加强InterSystems数据平台的安全。 1. InterSystems数据平台连接通道安全 客户端可以使用多种技术连接到InterSystems数据平台,包括ODBC/JDBC、Java、.net、TCP、Telnet、HTTP、SOAP、REST等。除了客户端的连接,InterSystems数据平台之间也有很多连接通道,例如高可用镜像成员之间、数据平台和Web网关之间… 这些连接通道都应该考虑使用SSL/TLS进行通讯加密,从而保护数据的安全和一致性。 1.1配置InterSystems数据平台的超级服务器接入通道加密 除了通过HTTP、SOAP、REST之外的客户端,其它的客户端都连接到InterSystems数据平台的超级服务器。InterSystems数据平台在系统范围内使用SSL/TLS协议为超级服务器端口通道加密。 配置步骤如下: 在管理门户中,通过路径 系统 > 安全管理 > SSL/TLS 配置,建立名为%SuperServer的SSL/TLS配置项。参考文档 在管理门户中,通过路径 系统 > 安全管理 > SSL/TLS 配置,在超级服务器SSL/TLS支持 选项上选中“要求”。它的三个选项分别为: 禁用(默认选项)- 拒绝使用TLS的客户端连接 启用 - 允许使用TLS的客户端连接,但不必要 要求 – 仅接受使用TLS的客户端连接 如果Telnet也要通过TLS加密传输,将上面配置的基础上,再建立一个名为%TELNET/SSL的SSL/TLS配置项,然后将上图的Telnet server SSL/TLS support 设置为“要求”。具体配置 1.2 配置客户端使用SSL/TLS连接到InterSystems数据平台的超级服务器 不同的客户端技术配置SSL/TLS的方式不同,具体的配置详见: Java .net ODBC/Studio/Windows Terminal Windows配置 这里以ODBC为例,看看Windows客户端上ODBC设置的步骤: 1. 在Windows客户端上下载IRIS服务器上的CA证书文件,并保存在指定目录。例如:c:\InterSystems\certificates\certificateSQLaaS.pem 2. 在Windows客户端上编辑并保存C:\Program Files (x86)\Common Files\InterSystems\IRIS\SSLDefs.ini,其中[IRISServer]是你起的SSL/TLS配置名,后面的Address和Port是 InterSystems数据平台的服务器地址和超级服务器端口号。[TLSConfig]是SSL/TLS的配置项,注意其中的CAfile是第一步得到的CA证书文件路径。 [IRISServer] Address=172.168.3.10 Port=1972 SSLConfig=TLSConfig [TLSConfig] TLSMinVersion=16 TLSMaxVersion=32 CipherList=ALL:!aNULL:!eNULL:!EXP:!SSLv2 Ciphersuites=TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256 KeyType=2 VerifyPeer=1 Password= CAfile=c:\InterSystems\certificates\certificateSQLaaS.pem 3. 配置Windows的ODBC DSN,选中“Password with SSL/TLS", 并在“SSL/TLS Server Name”中填写SSLDefs.ini中特定的配置名,例如:IRISServer 之后ODBC客户端就可以使用这个DSN通过TLS加密传输连接到InterSystems数据平台了。 1.3 安全建议 虽然不是三级等保必须的,建议配置和开启InterSystems数据平台的超级服务器SSL/TLS连接。 2. Web服务器 InterSystems 数据平台在安装时,可以选择安装一个私有的Apache,用于访问管理门户和基于HTTP的开发、测试,例如网页应用、SOAP和RESTful API。 这个私有Apache并不是全功能的,因此不应作为生产环境的Web服务器,尤其是生产环境有基于HTTP的服务、应用或接口时。这时,应该部署独立的Web服务器和InterSystems Web网关,连接到InterSystems的数据平台。并且应该配置HTTPS,而非使用无加密的HTTP。 InterSystems的数据平台支持Apache、IIS和Nginx等Web服务器。 2.1 独立Web服务器的配置 如何配置独立的Web服务器和InterSystems Web网关,如何配置Web服务器的HTTPS?请参考这篇非常棒的社区系列文章: WebGateway系列 2.2 安全建议 生产环境上,部署独立的Web服务器,而非使用InterSystems 数据平台的私有Web服务器。 Web服务器应使用HTTPS,而非HTTP,提供Web服务。 3. 服务与接口 InterSystems数据平台提供一系列服务和接口,用于各种外部系统和技术的接入,例如常见的ODBC/JDBC的SQL客户端、开发者使用的Studio、管理员常用的Telnet。另外,InterSystems数据平台组件和实例之间的连接也是通过服务实现的,例如Web网关和InterSystems数据平台之间的连接、配置为镜像高可用的多台InterSystems数据平台之间的连接。 3.1 InterSystems数据平台的服务 下表列出了InterSystems数据平台的服务和它们服务的对象: 服务名称 描述 %Service_Bindings 控制 SQL 或对象访问方式,包括Studio、XDBC客户端、Java、C++、ActiveX %Service_CacheDirect 控制 Caché 直连访问方式 %Service_CallIn 控制使用CallIn的C/C++应用的访问 %Service_ComPort 控制从Windows系统COM端口的访问 %Service_Console 控制Windows本地服务器上 CTERM (TRM:pid) 和 Windows 控制台访问 %Service_Terminal 控制UNIX, Linux, Mac本地服务器上的控制台访问 %Service_DataCheck 控制实例间数据一致性检查DataCheck时,作为数据源的访问 %Service_DocDB 控制文档数据库的访问 %Service_ECP 控制是否ECP %Service_Login 控制通过 SYSTEM.Security.Login的登录访问 %Service_Mirror 控制镜像成员访问 %Service_Monitor 控制 SNMP 和远程监视命令 %Service_Shadow 控制此系统是否可以是shadow来源 %Service_Sharding 控制是否可以作为分片服务器访问 %Service_Telnet 控制来自于Windows 服务器的本地或远程Telnet 会话访问 %Service_CSP %Service_WebGateway %Service_CSP(Caché/Ensemble)或%Service_WebGateway(IRIS)控制通过Web网关的访问,也就是web应用 %Service_Weblink 控制旧有的WebLink应用访问 3.2 InterSystems数据平台服务的安全选项 这些向外开放的服务和接口有多种机制保护安全: 是否启用 是否是公用服务(意味着所有用户都有权限) 身份认证的方式 接入客户端的IP限制 其它特殊限制 在管理门户>系统>安全管理>服务,可以对每一项服务进行单独的安全配置: 3.3 安全建议 关闭不必要的服务。 对开启的服务,应选择安全的认证方式,不应使用“未验证”方式。 进一步限定允许接入的客户端IP地址。 4. 用户认证 用户认证是保障数据安全的核心之一。 4.1 InterSystems数据平台的用户认证机制 InterSystems数据平台支持多种用户认证机制,包括: Kerberos 基于操作系统的认证 IRIS用户名/密码 LDAP 代理认证 – 用户自定义认证 无认证 – 无需用户认证,进来的用户自动为UnknownUser 二阶段认证 它同时可以开启和使用多种用户认证,允许用户使用不同的认证方式接入数据平台。在启用多种用户认证机制时,InterSystems数据平台会以一定优先顺序来应用用户认证机制: Kerberos > 基于操作系统的认证 > IRIS用户名/密码 >无认证 LDAP > 代理认证 >无认证 4.2 用户认证方式的设置 这些用户认证方式,可以在系统层面开启或禁用,也可以在服务/接口层面进行选择。对于InterSystems数据平台提供的Web应用,例如网页应用、SOAP服务和RESTful API,还可以在Web应用层面进行用户认证方式的配置。 系统层面的配置,在管理门户>系统>安全管理>Authentication/Web Session Options ; 服务层面的配置,见3.2; 应用层面的配置,将在后面的应用安全章节详细介绍。 4.3 安全建议 系统级禁用 “无认证”,和其它不需要使用的认证方式 系统级,采用更安全的认证方式 5. 用户授权 InterSystems数据平台提供一套基于角色的权限控制机制,它可以保障细颗粒度的数据与服务安全。 5.1基于角色的权限控制机制 在这套机制下,被保护的数据与服务被称之为资产。资产可以是任何具体事物,例如数据库、服务、平台应用、管理工具,甚至可以是抽象的事物,例如工作身份、“对患者联系方式的权限”。 权限控制机制是: InterSystems数据平台定义资源,对应一个或多个资产;系统已经定义了一系列系统资源,同时用户可以自定义资源。 对资源的许可,例如读、写、使用,就是权限; 将权限分配给InterSystems数据平台定义的角色和/或用户; 用户就具有了相应的资产权限。 5.2资源的权限配置 通过管理门户>系统>安全管理>资源,管理可以创建新资源、配置已有资源的权限。 以%开头的资源是系统已经创建好的资源,例如: %Admin_* 是工作身份资源 %DB_* 是数据库资源 %Service_* 是服务资源 %Ens_* 是互操作相关的资源 其中,对资源的权限可以被设置为“公有权限”,即所有用户都有相应的权限。 5.3 安全建议 用户自定义的数据库应该设置自己独立的资源,而非使用%DB_%DEFAULT 谨慎使用公共权限 创建自己需要保护的新资源
文章
Qiao Peng · 四月 11, 2022

InterSystems 数据平台与三级等保 - 第二篇

6. 用户与角色 InterSystems 数据平台对用户和角色提供全面的管理和安全配置功能。加强数据平台的安全,需要加强对于用户和角色的管理。 6.1 用户管理 系统提供了一系列预置的用户账户,这些账户管理对应特殊的系统功能: 用户 说明 UnknownUser 匿名用户,通过“未验证”方式登录到系统的用户 _SYSTEM SQL系统管理员 SuperUser 超级用户 Administrator 安装系统的用户 Admin 系统管理员 CSPSystem Web网关管理员 IAM IAM用户 _PUBLIC 内部使用 _Ensemble 内部使用 6.1.1 系统级用户安全配置 InterSystems数据平台有一些系统级别的用户安全配置,例如密码模式、密码有效天数、无效登录限制(多少次登录失败后要禁用用户账户)、非活动限制(多少天未登录后禁用用户账户)等。这些系统级配置通过管理门户>系统>安全管理>系统范围的安全参数: 三级等保对于用户的密码强度是有要求的。弱密码只需要0.19毫秒就能被破解,而8位强密码破解需要上百年。密码强度可以通过上面配置页面的密码模式或密码验证routine来配置: 密码模式只能配置简单的密码强度约束逻辑,例如3.32ANP意思是允许3位到32位长度到密码,密码可以由字符、数字和符号组成。 密码验证routine可以配置任意复杂的密码强度约束逻辑,它通过用户自定义的密码检查逻辑进行判断。例如要求“密码必须是包括数字、大写字母和半角符号的8位以上的字符串”,可以在%SYS命名空间下编写一个routine,里面提供密码验证逻辑的方法。方法名由自己决定,它有两个固定的参数Username和Password,您只要实现密码约束逻辑:如果符合约束,返回$$$OK,否则返回相应的错误提示即可。 这里给出一个routine示例,这个%SYS下的routine名为IRISPWD,里面的CHECK方法用于判断密码合规性,它利用正则表达式判断密码是否符合“必须是包括数字、大写字母和半角符号的8位以上的字符串”的约束,违反约束时给出提示错误。 #include %occInclude CHECK(Username,Password) PUBLIC { s tValid=(Password?8.E)&&(Password?.E1.U.E)&&(Password?.E1.N.E)&&(Password?.E1.P.E) q:(tValid=0) $$$ERROR($$$GeneralError,"密码需要是包括数字、大写字母和半角符号的8位以上的字符串") q $$$OK } 然后将方法调用的名称更新到“系统范围的安全参数”中的密码验证routine中。方法调用名称是方法名^Routine名,本示例为CHECK^IRISPWD。 设置好后即可生效,但要注意它不会对旧有密码进行验证。当设置或修改用户密码后保存时,它会进行检查,对违反约束的密码设置,会报如下错误提示: 6.1.2用户管理 通过管理门户>系统>安全管理>用户,可以创建、管理用户。在这里可以执行每个用户的初始密码设置、账户启用/禁用条件,用户的角色设置、SQL权限等管理。 另外,也可以查看用户的概要信息,它会显示用户的权限列表、登录历史等信息: 注意: CSPSystem用户是CSP网关登录到InterSystms IRIS/Cache'的用户。如果需要修改它的密码,需要先在IRIS/Cache'用户管理页面修改CSPSystem的密码,然后再登录到CSP网关上修改CSP网关连接IRIS服务器的账户信息,保持二者密码一致。1. 登陆到私有Apache的CSP网关或独立安装的Web服务器的CSP网关,访问http://<IP+端口>/csp/bin/Systems/Module.cxw 2. 修改CSP网关连接IRIS服务器的账户信息: 2.1 Configuration>Default Parameters>Security>User Name 和Password2.2 Configuration>Server Access>Connection Security>User Name 和Password 6.2 角色管理 InterSystems数据平台预置了一些%开头的系统角色,例如%Developer开发者角色、%Manager系统管理员角色、%Operator系统操作员角色。 其中%All是一个特殊角色,它是超级用户角色,属于这个角色下的用户都是超级用户。因此属于这个角色的用户数量不宜过多,当然也不建议少于2个,以避免密码遗失造成无法管理系统而只能进入紧急模式。 6.3 安全建议 1.仅管理员有%All角色,尤其要确保UnknownUser没有%All角色 2.删除不需要的系统角色和系统用户 3.要求用户账号更安全的密码模式 4.设置密码错误数次后停用账号 7. 数据安全 InterSystems数据平台提供了丰富的数据安全特性,包括数据与数据库加密、数据访问控制机制。这里相当多的特性都是三级等保要求的。 7.1 数据加密 InterSystems数据平台内建多种加密算法,包括AES CBC (128, 192, 256位)、HMAC、MD5、SHA-1、SHA-512、PKCS、PBKDF2、Base64等。同时,它可以直接调用外部的Python、Java和.net算法库,实现包括国密SM算法在内的算法扩展。 它支持对全数据库加密,或仅对数据元素加密。 7.1.1 全数据库加密 全数据加密时,InterSystems数据平台使用AES加密算法,自动负责数据库数据的加解密。加密的数据库在加载时,需要向系统提供密钥。通常密钥保存在可移除的设备上,例如U盘,仅在加密数据库加载时使用,加载后就可以移除并保存在安全的地方。 InterSystems数据平台的数据库和命名空间架构让用户可以将需要加密保护的数据,例如患者基本信息数据和支付数据单独保存在一个较小的数据库中。 在全数据库加密的情况下,可以对日志、审计日志都进行加密,从而避免任何的数据泄密渠道。这样,即便数据库文件、日志文件和审计日志被盗走,没有密钥文件都无法解密数据。 创建一个新密钥文件及新的加密数据库的过程非常简单,在管理门户即可完成: 产生密钥文件。只有管理员才有权限产生密钥文件。 输入密钥文件产生路径、管理员账户、密钥文件管理密码、AES加密位数,保存时会产生用于加密的密钥文件。 注意,产生的密钥文件的管理是需要权限的 – 只有密钥管理员才可以激活该密钥文件并使用它进行数据库加密。在密钥文件产生后,尽快加入多个可以管理该密钥的管理员,并为他们设置不同的密钥密码,以避免一个密钥管理员账户失效。 密钥文件产生后,你就可以将其拷贝到安全的位置,并将原始产生的文件删除。如果你有多个密钥,应记住密钥ID (如下图的0535458F-A895-4915-BADF-2C257602880D)和密钥文件、密码的关系。 激活密钥文件 在InterSystems数据平台实例上激活密钥,才能使用它进行数据库加解密。只有密钥管理员,使用密钥文件的密码才能激活密钥。 每个实例可以激活多个密钥,因为你可能有使用不同密钥加密后的数据库文件。可以设置某个密钥为默认密钥,新产生的加密数据库会使用默认密钥加密;同时可以设置某个密钥文件为默认的Journal日志密钥,新的Journal日志会使用默认Journal密钥加密。 这里还可以设置密钥使用的方式:“交互”或“无人参与”。 “无人参与”需要将密钥文件保存在一个InterSystems数据平台启动时可以访问到的固定路径上,因此不推荐使用。“交互”方式下,InterSystems数据平台会在启动和加载加密数据库时向管理员询问密钥位置,因此更加安全。 创建加密的数据库: 在数据库创建过程中,选择加密数据库。这样InterSystems数据平台会使用当前默认的密钥进行加密。 现在你就有了一个加密的数据库了,里面的任何数据都是被加密的。即便数据库文件被copy走,只要没有密钥文件,这个数据库就无法被加载或解密其中的数据。 在今后的InterSystems数据库平台的启动过程中,都将要求输入加密密钥文件的完整路径、密钥管理员账户和密钥文件密码: 如果要对之前未加密的数据库加密、或者将加密数据库重新部署为不加密的数据库、或者为加密数据库更换加密密钥,这些操作需要通过^EncryptionKey 管理工具完成,而不能在管理门户中完成。参见文档 7.1.2 数据元素加密 除了全数据库加密,用户也可以选择通过代码控制仅对特定数据元素加密,因此它可以控制非常细颗粒度的加密策略。 InterSystems数据平台提供系统类%SYSTEM.Encryption,里面有密钥创建和管理、加密解密的方法。用户开发的程序可以使用这些方法进行密钥管理和加解密工作。 如何使用的文档在这里。 7.2 数据访问控制 InterSystems数据平台提供多个层面的数据访问控制机制。包括: 数据库层面的访问权限控制,即数据库读、写权限控制 SQL层面的访问权限控制,包括 SQL操作的权限,例如创建表和视图的权限 对表、视图级别的访问权限 对存储过程的执行权限 行级安全 – 例如每个医生只能看自己的出诊记录 列级安全 – 例如医生角色可以看到患者表中除了患者支付卡号列之外的其它数据 这些数据访问控制机制可以自由组合,满足严格的数据访问控制。 7.3 安全建议 对敏感数据进行全数据库加密,并保存好密钥文件和密钥文件密码 合理的数据读写权限 必要时,添加行级和列级安全
文章
Frank Ma · 五月 24, 2022

如何轻松开始在Adaptive Analytics + InterSystems Reports中工作

让我们假设我们已经将一个数据源连接到Adaptive Analytics,创建了一个项目并在那里添加了表。 现在我们来准备Adaptive Analytics的工作。首先,我们需要从表中选择数据,使其可用于未来的报告。要做到这一点,我们需要从表的列中创建维度。创建维度通常是为了将我们的数据分解成不同的类别,例如用户住在哪个城市,或者购买是在哪个月进行的。然而,没有什么可以阻止我们从数字数据中创建维度,这样我们就可以在Intersystems Reports Designer中对它们应用函数。 创建维度的工具位于界面的右侧,如下图所示。要创建一个新的维度,右击位于 "过滤器 "(Filter)行右侧的汉堡包按钮,选择 "创建维度 "(Create Dimension),如图所示。 将出现以下窗口: 在创建了一个维度后,你可以使其具有层次性。要做到这一点,在左边表格的尺寸上双击鼠标左键,进入层次结构编辑器。 通过点击层次结构旁边的三个点,我们可以在层次结构中创建一个新的维度。在菜单中,维度可以在层次结构中向上/向下移动。由于层次结构的存在,我们可以制作不同层次的数据细节。例如,我们可以指定有多少人从国家、地区、城市访问过该网站。 你可以使用维度来创建表之间的关系。要做到这一点,你需要使用鼠标左键拖动表的所需字段,并将其放到所需的高亮维度中。链接创建窗口将出现。点击保存,我们的连接就准备好了。 除了表中的实际数据外,在Adaptive Analytics中,我们可以根据应用于特定列的各种操作创建测量值(measure)。测量值是数据的数字显示--用户数量、购买金额、观看视频的平均时间,等等。 要创建一个测量值(Measure),我们采用与维度相同的原则,但使用 "测量值 "(Measures)标签。 通过点击汉堡包按钮并选择 "添加测量值"(Add measure),我们调出以下窗口: '测量值名称'(Measure name)是将要显示在Adaptive Analytics界面的名称。 “查询名称 "(Query name)是将在Intersystems报告设计器中显示的名称。它是根据列名自动生成的,但你也可以自己设置。 '描述'(Description)是指Adaptive Analytics中可见的描述。 ”来源 "(Sources)定义了从哪张表和哪一列中获取数据用于测量。"聚合处理 "(Aggregation Handling)显示了我们对数据所使用的函数。函数的列表见下文。默认选择是"汇总"(Sum)。 “数据处理和格式化 "(Data Handling and Formatting)决定了如果测量值与未定义测量值的维度一起使用,将会发生什么。你应该把它留在默认状态。 ”在已发布的数据源中的可见性 "(Visibility in Published Data Sources)指定该测量值是否在Intersystems Reports Designer (报告设计器) 中可用。 你可以按维度分割测量值。例如,我们有一个显示平均数的测量值,我们用一年内每天的数据来计算一列的数据。如果我们把这个测量值分布在一个包含月份的维度上,我们将得到每个月的平均值。 要了解连接到Adaptive Analytics的数据中的内容,你可以使用立方体数据预览(Cube Data Preview)工具。你可以通过点击工作区左上角的标签进入它。 通过在一个轴上指定一个维度,在另一个轴上指定一个测量值,我们可以得到每个维度值的测量值。在这种情况下,下面你可以看到表格中每个日期的记录数。 在创建了所有我们需要的测量值、维度和关系之后,现在我们来发布我们的项目。要做到这一点,请到项目主页面左上角的标签上,点击 "发布 "(Publish)按钮,然后在出现的所有窗口上点击 "下一步 "(Next)按钮。 现在我们可以开始注意左边的窗口,这里有两个部分。"草稿"(Draft),我们可以在这里编辑我们的项目,"发布"(Publish),显示项目的发布版本。通过点击 "发布的项目"(Published project),选择立方体(cube),并进入其 "连接 "(Connect)标签。在这里我们可以看到所有必要的数据,以便将Intersystems Reports Designer连接到我们的项目。 我们已经学会了使用Adaptive Analytics所需要的一切。现在我们可以继续在InterSystems Reports Designer中工作了。 我需要提到的是,Intersystems Reports Designer 17.1版需要JDK 16版才能工作,它不能在以后的版本上运行。 首先,你需要安装JDBC连接到Adaptive Analytics的驱动程序。 下面是所需JAR文件的链接。JDBC驱动本身必须与服务器上使用的驱动兼容。我们使用足够老的版本,这样我们就不会因为服务器上的Hive版本比我们的老而导致错误。 为了方便起见,我们将所有必要的库收集在一个档案中,你可以从链接中下载。 https://github.com/teccod/Logi-JDBC-drivers 这些文件必须放在lib文件夹中,路径是LogiReport/Designer/lib。 启动Intersystems Reports Designer并关闭 "开始 "(Start)页面。现在你可以发现自己处于Intersystems Reports Designer的工作区。默认情况下,它会打开用户正在使用的最后一个目录或与Intersystems Reports Designer一起安装的预装目录。 进入 "文件 "(File)部分,点击 "新目录"(New Catalog);填写目录的名称、数据源的名称和文件应保存的位置。 Intersystems Reports Designer为我们创建了一个空的数据源。右键单击它并选择 "新建JDBC连接"(New JDBC connection)。 在 "Driver "一行,我们写上我们的驱动程序--org.apache.hive.jdbc.HiveDriver。 我们从Adaptive Analytics的 "连接 "(Connect)标签的JDBC字段中获取URL,并填写用户名和密码。 连接已经建立,但是项目中还没有立方体被加载到其中。右键单击 "表"(Tables),然后单击 "添加表"(Add tables),选择所需的立方体;用 "添加按钮 "(Add button)添加它们,然后按 "完成 "(Done)来完成这一过程。如果当你选择的数据方案与默认打开的方案不同时,没有显示这些表,请使用 "刷新 "(Refresh)按钮。 在添加了我们所需要的一切之后,我们在项目中拥有了可用的维度和测量值,我们几乎可以开始创建一个报告了。 为了使用可用的数据,我们必须提出一个请求。在这个请求中,我们可以对数据进行必要的限制(不显示取消的订单,不显示当前月份的数据,等等),只取我们需要的那部分数据。 要在 "主页 "(Home)或 "文件 "(File)标签上创建一个查询,选择 "新建 "(New)并选择 "查询"(Query)。我们挑选数据源,填写查询名称,打开我们的源,"表 "(Tables)并使用箭头将必要的表添加到查询中。 我们进入查询编辑器窗口(Query Editor): 在那里,通过设置必要的复选框或勾选*字段旁边的方框,选择必要的或表格中的所有字段。在 "菜单 "(Menu)项中,我们看到了几个功能,其中最有趣的是数据过滤。 在这里我们可以添加条件,这些条件将用SQL语言写在 "SELECT "语句的 "WHERE "部分(或者简单地说,就是切断指定表达式的数据的条件)。在我们的案例中,我们可以写上日期小于某个值,处于某个值的范围内,等等。 在 "查询编辑器 "(Query Editor)中,我们还可以添加计算列来丰富我们的数据。创建时可以使用的函数取决于数据源提供了哪些函数。Adaptive Analytics不提供任何函数,所以我们只能使用内置的Logi函数(这是最简单的数学和逻辑运算符)。 如果查询中有多个表,那么你可以通过用鼠标左键从一个字段拖动链接到另一个字段来设置它们之间的链接。在SQL查询代码中,这些关系将显示为WHERE table_name1.field_name = table_name2.field_name。 当你完成编辑请求后,点击 "确定 "(OK)按钮。如果有必要,你可以再创建几个带有不同过滤器或字段的查询。 现在你已经准备好创建报告了。我们将在下一篇文章中讨论其创建过程。
公告
Louis Lu · 十二月 16, 2021

InterSystems IRIS 和 IRIS for Health 2021.2 预览版发布

InterSystems IRIS、IRIS for Health 以及 HealthShare Health Connect 的 2021.2 版本的预览版现已发布。 由于这是一个预览版,我们希望在下个通用版本发布之前了解您对这个新版本的体验。请通过开发者社区分享您的反馈,以便我们能够共同打造一个更好的产品。 InterSystems IRIS 数据平台 在 2021.2 版本中使开发、部署和管理用于连接数据、应用孤岛的增强型应用和业务流程变得更加容易。它有许多新的功能,包括: 为应用程序和界面开发人员提供的增强功能: 嵌入式Python 使用 Python 进行的互操作性Production开发 对Visual Studio Code ObjectScript扩展包的更新 增加了新的商业服务和操作,允许用户用最少的自定义编码来设置和运行SQL查询 对数据分析和人工智能的增强: 新的SQL LOAD命令有效地将CSV和JDBC源的数据加载到表中 增强自适应分析功能 对云和云上运营任务的增强: 新的云连接器使得在 InterSystems IRIS 应用程序中访问和使用云服务变得简单。 IKO的改进提高了Kubernetes 资源的可管理性 针对数据库和系统管理员的增强功能: 在线分片再平衡可以在不中断操作的情况下自动在各节点间分配数据 自适应 SQL 引擎使用快速块采样和自动化来收集高级表的统计数据,并利用运行时信息来改进查询规划 通过新的流类型数据和日志文件压缩设置,减少InterSystems IRIS的存储需求 使用系统提供的库,支持 TLS 1.3 和 OpenSSL 1.1.1 新的^TRACE工具报告详细的进程统计数据,如缓存点击率和读取率 关于所有这些功能的更多细节可以在产品文档中找到。 InterSystems IRIS 2021.1文档和发布说明 InterSystems IRIS for Health 2021.1 文档和发布说明 HealthShare Health Connect 2021.1 文档和发布说明 InterSystems IRIS 2021.2是一个持续交付(CD)版本,现在为所有支持的平台提供经典安装包,以及OCI(Open Container Initiative)又称Docker容器格式的容器镜像。 容器镜像可用于符合OCI标准的Linux x86-64和Linux ARM64的运行时引擎,详见支持平台。 每个产品的完整安装包都可以从WRC的产品下载网站获得。使用 "自定义 "安装选项,用户可以选择他们需要的选项,如 InterSystems Studio 和IntegratedML,以合理地缩小安装内容。 安装包和预览密钥可以从WRC的预览下载站点获得。 企业版、社区版和所有相应组件的容器镜像可以通过以下命令从 InterSystems容器注册中心获得。 docker pull containers.intersystems.com/intersystems/iris:2021.2.0.617.0 docker pull containers.intersystems.com/intersystems/iris-ml:2021.2.0.617.0 docker pull containers.intersystems.com/intersystems/irishealth:2021.2.0.617.0 docker pull containers.intersystems.com/intersystems/irishealth-ml:2021.2.0.617.0 关于可用镜像的完整列表,请参考ICR文档。 另外,所有容器镜像的tarball版本可以通过WRC的预览版下载网站获得。 该预览版的构建号是2021.2.0.617.0。
文章
Claire Zheng · 十月 22, 2021

InterSystems 2021全球线上峰会邀您参会(内含福利)

10月26日-29日,InterSystems 2021全球线上峰会将聚焦于“Analytics”,为您提供全球先进经验和分享。 除了丰富的演讲外,针对使用InterSystems技术的开发者们,InterSystems的认证团队提供了最新福利,注册参加InterSystems2021全球线上峰会,可在2021年12月31日前免费参加以下几项认证考试(价值150美元,每人限选一项): InterSystems IRIS Core Solutions Developer Specialist 考核认证使用ObjectScript和其他InterSystems IRIS®技术构建应用程序的开发人员的核心技能。 HealthShare HealthConnect HL7 Interface Specialist 考核认证使用Health Connect构建和测试HL7®v2 新产品的开发人员的核心技能。 HealthShare Unified Care Record Technical Specialist 考核认证实施、扩展和管理HealthShare®统一健康档案(Unified Care Record)各个方面的技术专业人员的核心技能。 HealthShare Patient Index Technical Specialist (Beta) 考核认证实施、培训和支持HealthShare Patient Index各个方面的技术专业人员的核心技能。 如果您对该项目感兴趣,请在峰会结束后至11月12日(含)发邮件至wechat@intersystems.com进行咨询、申请,申请通过后,需要在12月31日前完成考试。 10月26日-27日,我们为中国用户专门开通了本地直播平台,欢迎点击免费注册参会。
文章
Jingwei Wang · 十月 8, 2022

在InterSystems IRIS建立 JDBC ODBC 网关连接 - mysql

本篇文章使用的InterSystems IRIS for Windows (x86-64) 2021.1 (Build 215U) Wed Jun 9 2021 09:39:22 EDT Mysql ODBC 和 JDBC 驱动版本:8.0.28 使用ODBC 网关连接mysql 下载MySQL驱动安装包: https://downloads.mysql.com/archives/c-odbc/ 定义DSN (此DSN用来连接远程MySQL数据库) 打开Administrative Tools 打开ODBC Data Sources Administrator(32-bit 或者 64-bit) 选择‘System DSN’,点击右边 ‘Add’,弹出‘Create New Data Source’窗口 选择安装好的mysql驱动,然后按照下图配置DSN 点击 ’Test‘ 测试连接 如果出现host 'ip' is not allowd to connect to this MySQL server 错误,说明要连接的MySQL不允许远程登录,需要更新MySQL上面的host privileges 来同意远程登录 在InterSystems IRIS管理门户中,建立SQL Gateway 连接 系统管理 -> 配置 -> SQL 网管连接 -> 新建连接 ->选择ODBC,填写以下连接信息。填写完配置信息,点击’测试连接‘,左下角会出现 ’连接成功‘,然后点击 ’保存‘。 使用JDBC 网关连接mysql 下载my JDBC 驱动 https://dev.mysql.com/downloads/connector/j/8.0.html 在管理门户中,建立SQL Gateway 连接 系统管理 -> 配置 -> SQL 网管连接 -> 新建连接 -> 选择JDBC,填写以下连接信息。填写完配置信息,点击’测试连接‘,左下角会出现 ’连接成功‘,然后点击 ’保存‘。
文章
Hao Ma · 一月 10, 2021

InterSystems 最佳实践系列---APM – 监控 SQL 查询性能

自 Caché 2017 以后,SQL 引擎包含了一些新的统计信息。 这些统计信息记录了执行查询的次数以及运行查询所花费的时间。 对于想要对包含许多 SQL 语句的应用程序的性能进行监控和尝试优化的人来说,这是一座宝库,但访问数据并不像一些人希望的那么容易。 本文和相关的示例代码说明了如何使用这些信息,以及如何例行提取每日统计信息的摘要,并保存应用程序的 SQL 性能的历史记录。 记录了什么? 每次执行 SQL 语句时,都记录花费的时间。 这是非常轻量的操作,无法关闭。 为了最大程度地降低开销,统计信息保留在内存中并定期写入磁盘。 数据包括一天中执行查询的次数以及所花费的平均时间和总时间。 数据不会立即写入磁盘,并且在写入之后,统计信息将由“更新 SQL 查询统计信息”任务更新,该任务通常计划为每小时运行一次。 该任务可以手动触发,但是如果你希望在测试查询时实时查看统计信息,则整个过程需要一点耐心。 警告:在 InterSystems IRIS 2019 及更早版本中,不会针对已使用 %Studio.Project:Deploy 机制部署的类或例程中的嵌入式 SQL 收集这些统计信息。 示例代码不会有任何中断,但这可能会使你产生误导(我被误导过),让你以为一切正常,因为没有查询显示为高开销。 如何查看信息? 你可以在管理门户中查看查询列表。 转到 SQL 页面,点击“SQL 语句”选项卡。 对于你正在运行并查看的新查询,这种方式很好;但是如果有数千条查询正在运行,则可能变得难以管理。 另一种方法是使用 SQL 搜索查询。 信息存储在 INFORMATION_SCHEMA 模式的表中。 该模式含有大量表,我在本文的最后附上了一些 SQL 查询示例。 何时删除统计信息? 每次重新编辑查询时会删除其数据。 因此对于动态查询,这可能意味着清除缓存的查询时。 对于嵌入式 SQL,则意味着重新编译在其中嵌入 SQL 的类或例程时。 在活跃的站点上,可以合理预期统计信息将保存超过一天,但是存放统计信息的表不能用作运行报告或长期分析的长期参考源。 如何汇总信息? 我建议每天晚上将数据提取到永久表中,这些表在生成性能报告时更易于使用。 如果在白天编译类,可能会丢失一些信息,但这不太可能对慢速查询的分析产生任何实际影响。 下面的代码示例说明了如何将每个查询的统计信息提取到每日汇总中。 它包括三个简短的类: * 一个应在每晚运行的任务。 * DRL.MonitorSQL 是主类,用于从 INFORMATION_SCHEMA 表提取数据并存储。 第三个类 DRL.MonitorSQLText 是一个优化类,它存储一次(可能很长的)查询文本,并且只将查询的哈希存储在每天的统计信息中。 示例说明 该任务提取前一天的信息,因此应安排在午夜后不久执行。 你可以导出更多历史数据,只要其存在。 要提取过去 120 天的数据 Do ##class(DRL.MonitorSQL).Capture($h-120,$h-1) 该示例代码直接读取全局 ^rIndex,因为最早版本的统计信息未将日期公开给 SQL。 我所包括的变体将循环实例中的所有命名空间,但这并不总是合适的。 如何查询已提取的数据 提取数据后,您可以通过运行以下语句查找最繁重的查询 SELECT top 20 S.RunDate,S.RoutineName,S.TotalHits,S.SumpTIme,S.Hash,t.QueryText from DRL.MonitorSQL S left join DRL.MonitorSQLText T on S.Hash=T.Hash where RunDate='08/25/2019' order by SumpTime desc   此外,如果选择了开销大的查询的哈希,可以通过以下语句查看该查询的历史记录   SELECT S.RunDate,S.RoutineName,S.TotalHits,S.SumpTIme,S.Hash,t.QueryText from DRL.MonitorSQL S left join DRL.MonitorSQLText T on S.Hash=T.Hash where S.Hash='CgOlfRw7pGL4tYbiijYznQ84kmQ=' order by RunDate   今年早些时候,我获取了一个活跃站点的数据,然后查看了开销最大的查询。 有一个查询的平均时间不到 6 秒,但每天被调用 14000 次,加起来每天消耗的时间将近 24 小时。 实际上,一个核心完全被这个查询占用。 更糟糕的是,第二个查询要花一个小时,它是第一个查询的变体。   运行日期 例程名称 总命中次数 总时间 哈希 查询文本(有节略) 03/16/2019   14,576 85,094 5xDSguu4PvK04se2pPiOexeh6aE= DECLARE C CURSOR FOR SELECT * INTO :%col(1) , :%col(2) , :%col(3) , :%col(4)  … 03/16/2019   15,552 3,326 rCQX+CKPwFR9zOplmtMhxVnQxyw= DECLARE C CURSOR FOR SELECT * INTO :%col(1) , :%col(2) , :%col(3) , :%col(4) , … 03/16/2019   16,892 597 yW3catzQzC0KE9euvIJ+o4mDwKc= DECLARE C CURSOR FOR SELECT * INTO :%col(1) , :%col(2) , :%col(3) , :%col(4) , :%col(5) , :%col(6) , :%col(7) , 03/16/2019   16,664 436 giShyiqNR3K6pZEt7RWAcen55rs= DECLARE C CURSOR FOR SELECT * , TKGROUP INTO :%col(1) , :%col(2) , :%col(3) , .. 03/16/2019   74,550 342 4ZClMPqMfyje4m9Wed0NJzxz9qw= DECLARE C CURSOR FOR SELECT … 表 1:客户站点的实际结果   INFORMATION_SCHEMA 模式中的表 除了统计信息外,此模式中的表还会跟踪查询、列、索引等的使用位置。 通常,SQL 语句是起始表,它的连接方式类似于“Statements.Hash=OtherTable.Statement”。 直接访问这些表以查找一天中开销最大的查询,这一操作的等效查询是...   SELECT DS.Day,Loc.Location,DS.StatCount,DS.StatTotal,S.Statement,S.Hash FROM INFORMATION_SCHEMA.STATEMENT_DAILY_STATS DS left join INFORMATION_SCHEMA.STATEMENTS S on S.Hash=DS.Statement left join INFORMATION_SCHEMA.STATEMENT_LOCATIONS Loc on S.Hash=Loc.Statement where Day='08/26/2019' order by DS.stattotal desc   无论你是否考虑建立一个更系统的过程,我都建议每个使用 SQL 处理大型应用程序的人今天都运行这个查询。 如果某个特定查询显示为高开销,则可以通过运行以下语句获取历史记录 SELECT DS.Day,Loc.Location,DS.StatCount,DS.StatTotal,S.Statement,S.Hash FROM INFORMATION_SCHEMA.STATEMENT_DAILY_STATS DS left join INFORMATION_SCHEMA.STATEMENTS S on S.Hash=DS.Statement left join INFORMATION_SCHEMA.STATEMENT_LOCATIONS Loc on S.Hash=Loc.Statement where S.Hash='jDqCKaksff/4up7Ob0UXlkT2xKY=' order by DS.Day     每日提取统计信息的代码示例 标准免责声明 - 此示例仅用于说明。 不对其提供支持,也不保证其有效。 Class DRL.MonitorSQLTask Extends %SYS.Task.Definition{Parameter TaskName = "SQL Statistics Summary";Method OnTask() As %Status{              set tSC=$$$OK              TRY {                             do ##class(DRL.MonitorSQL).Run()              }              CATCH exp {                            set tSC=$SYSTEM.Status.Error("Error in SQL Monitor Summary Task")              }              quit tSC }}   Class DRL.MonitorSQLText Extends %Persistent{/// Hash of query textProperty Hash As %String;  /// query text for hashProperty QueryText As %String(MAXLEN = 9999);Index IndHash On Hash [ IdKey, Unique ];} /// Summary of very low cost SQL query statistics collected in Cache 2017.1 and later. /// Refer to documentation on "SQL Statement Details" for information on the source data. /// Data is stored by date and time to support queries over time. /// Typically run to summarise the SQL query data from the previous day.Class DRL.MonitorSQL Extends %Persistent{/// RunDate and RunTime uniquely identify a runProperty RunDate As %Date;/// Time the capture was started/// RunDate and RunTime uniquely identify a runProperty RunTime As %Time;/// Count of total hits for the time period for Property TotalHits As %Integer;/// Sum of pTimeProperty SumPTime As %Numeric(SCALE = 4);/// Routine where SQL is foundProperty RoutineName As %String(MAXLEN = 1024);/// Hash of query textProperty Hash As %String;Property Variance As %Numeric(SCALE = 4);/// Namespace where queries are runProperty Namespace As %String;/// Default run will process the previous days data for a single day./// Other date range combinations can be achieved using the Capture method.ClassMethod Run(){              //Each run is identified by the start date / time to keep related items together                           set h=$h-1              do ..Capture(+h,+h)}/// Captures historic statistics for a range of datesClassMethod Capture(dfrom, dto){              set oldstatsvalue=$system.SQL.SetSQLStatsJob(-1)                             set currNS=$znspace                set tSC=##class(%SYS.Namespace).ListAll(.nsArray)                set ns=""      set time=$piece($h,",",2)      kill ^||TMP.MonitorSQL                do {                               set ns=$o(nsArray(ns))                               quit:ns=""                               use 0 write !,"processing namespace ",ns                               zn ns                                           for dateh=dfrom:1:dto {                                                          set hash=""                                                          set purgedun=0                                                          do {                                                                        set hash=$order(^rINDEXSQL("sqlidx",1,hash))                                                                        continue:hash=""                                                                        set stats=$get(^rINDEXSQL("sqlidx",1,hash,"stat",dateh))                                                                        continue:stats=""                                                                        set ^||TMP.MonitorSQL(dateh,ns,hash)=stats                                                                                                                                 &SQL(SELECT  Location into :tLocation FROM INFORMATION_SCHEMA.STATEMENT_LOCATIONS WHERE Statement=:hash)                                                                        if SQLCODE'=0 set Location=""                                                                        set ^||TMP.MonitorSQL(dateh,ns,hash,"Location")=tLocation                                                                                                                                 &SQL(SELECT  Statement INTO :Statement FROM INFORMATION_SCHEMA.STATEMENTS WHERE Hash=:hash)                                                                        if SQLCODE'=0 set Statement=""                                                                        set ^||TMP.MonitorSQL(dateh,ns,hash,"QueryText")=Statement                                                          } while hash'=""                                                                                                    }                } while ns'=""                zn currNS                set dateh=""                do {                               set dateh=$o(^||TMP.MonitorSQL(dateh))                               quit:dateh=""                               set ns=""                               do {                                             set ns=$o(^||TMP.MonitorSQL(dateh,ns))                                             quit:ns=""                                             set hash=""                                             do {                                                         set hash=$o(^||TMP.MonitorSQL(dateh,ns,hash))                                                          quit:hash=""                                                         set stats=$g(^||TMP.MonitorSQL(dateh,ns,hash))                                                          continue:stats=""                                                          // The first time through the loop delete all statistics for the day so it is re-runnable                                                          // But if we run for a day after the raw data has been purged, it will wreck eveything                                                          // so do it here, where we already know there are results to insert in their place.                                                          if purgedun=0 {                                                                        &SQL(DELETE FROM websys.MonitorSQL WHERE RunDate=:dateh )                                                                        set purgedun=1                                                          }                                                                                                                   set tObj=##class(DRL.MonitorSQL).%New()                                                          set tObj.Namespace=ns                                                          set tObj.RunDate=dateh                                                          set tObj.RunTime=time                                                          set tObj.Hash=hash                                                          set tObj.TotalHits=$listget(stats,1)                                                          set tObj.SumPTime=$listget(stats,2)                                                          set tObj.Variance=$listget(stats,3)                                                          set tObj.Variance=$listget(stats,3)                                                                                                                  set queryText=^||TMP.MonitorSQL(dateh,ns,hash,"QueryText")                                                         set tObj.RoutineName=^||TMP.MonitorSQL(dateh,ns,hash,"Location")                                                                                                             &SQL(Select ID into :TextID from DRL.MonitorSQLText where Hash=:hash)                                                          if SQLCODE'=0 {                                                                        set textref=##class(DRL.MonitorSQLText).%New()                                                                        set textref.Hash=tObj.Hash                                                                        set textref.QueryText=queryText                                                                        set sc=textref.%Save()                                                          }                                                                                                                  set tSc=tObj.%Save()                                                                                                                   //avoid dupicating the query text in each record because it can be very long. Use a lookup                                                          //table keyed on the hash. If it doesn't exist add it.                                                          if $$$ISERR(tSc) do $system.OBJ.DisplayError(tSc)                                                                                                                   if $$$ISERR(tSc) do $system.OBJ.DisplayError(tSc)                                             } while hash'=""                               } while ns'=""                                                                         } while dateh'=""                                                           do $system.SQL.SetSQLStatsJob(0)}Query Export(RunDateH1 As %Date, RunDateH2 As %Date) As %SQLQuery{SELECT S.Hash,RoutineName,RunDate,RunTime,SumPTime,TotalHits,Variance,RoutineName,T.QueryText              FROM DRL.MonitorSQL S LEFT JOIN DRL.MonitorSQLText T on S.Hash=T.Hash              WHERE RunDate>=:RunDateH1 AND RunDate
公告
Claire Zheng · 一月 7, 2021

Global Masters 奖励计划:1.5 小时的 InterSystems 专家咨询

亲爱的社区用户,您好! 您知道吗,在 Global Masters,您可以兑换关于以下任何 InterSystems 产品的 InterSystems 专家咨询:InterSystems IRIS数据平台、IRIS医疗版、互操作平台 (Ensemble)、IRIS Analytics (DeepSee)、Caché、HealthShare统一的健康档案。 我们还有一个振奋人心的消息要分享,我们现在可以提供以下语言的咨询: 英语、葡萄牙语、俄语、德语、法语、意大利语、西班牙语、日语、汉语 而且! 咨询时长延长到 1.5 小时,让您与专家深入探讨主题。 如果您有兴趣,不要犹豫,快来 Global Masters 兑换奖励吧! 如果您还不是 Global Masters 的会员,欢迎您“点击此处加入”点击 InterSystems 登录按钮,然后使用您的 InterSystems WRC 凭据)。 要了解关于 Global Masters 的更多信息,请阅读文章:认识Global Masters 倡导中心,从这里开始! 让我们在 InterSystems Global Masters 上见!🙂
文章
Qiao Peng · 一月 8, 2021

InterSystems IRIS 和 Caché 中的多模型数据并行处理

众所周知,InterSystems IRIS 提供了很多的工具来提升应用系统可伸缩性。尤其在提升数据并行处理能力方面,InterSystems 做了很多努力,例如在 SQL 查询中使用并行处理,以及在 IRIS中引入最具吸引力的特征:分片(sharding)。然而,许多成熟的开发成果最初是在 Caché中完成的,而且已经迁移到 IRIS 中。这些成熟的开发成果大都使用 DBMS(数据库管理系统)的多模型功能,实现在单独的数据库中共存不同的数据模型。例如, [HIS qMS](https://openexchange.intersystems.com/package/HIS-qMS) 数据库同时包含语义关系(电子病历)、传统关系(与 PACS 的交互)和层次数据模型(实验室数据以及与其他系统的集成)。这些数据模型大多是通过 [SP.ARM](https://openexchange.intersystems.com/company/SP-ARM) 的 qWORD 工具(一种直接访问 Global的小型数据库管理系统)实现的。遗憾的是,由于查询未使用 IRIS SQL,无法利用并行查询处理的新功能进行扩展。 而且,随着数据库规模的不断增长,大型关系型数据库所固有的大多数问题开始出现在非关系型数据库中。这就是我们关注可用于扩展的并行数据处理技术的一个主要原因。 在本文中,我将围绕多年来在解决任务时用到的并行数据处理展开多方位讨论,而这些是我在大数据问题探讨中很少提到的。我将重点讨论数据库的技术改造,或者更确切地说,是数据库转换技术。 众所周知,在系统开发的早期阶段(通常远远早于项目完成的时间)就已经选择好了数据模型、存储架构以及软件和硬件平台。但是在系统完成部署几年后,通常会因为这样或那样的原因需要对数据进行迁移。下面是一些常见的任务(所有示例均为真实案例): 1. 一家公司正计划走向国际市场,必须将其 8 位编码的数据库转换为 Unicode 格式。 2. 将过时的服务器替换为新的服务器时,但是由于许可限制,无法在服务器之间进行日志的无缝传输(使用 IRIS 的系统功能 Mirroring 或 Shadowing),或者当在您尝试处理任务时,缺少满足如 1 提出的这种需求。 3. 你需要更改数据库之间的 Global 分配,例如将一个包含图像的较大的 Global 迁移到单独的数据库。 你可能会问,这些方案有那么难吗?只需要停止旧系统,导出数据,然后导入到新系统中就可以了。但是,如果你正在处理的是几百 GB(甚至几 TB)的数据库,而且系统在 7x24 运行,那么就无法使用标准的 IRIS 工具解决上述这些任务了。 ## 实现任务并行处理的基本方法 ### "垂直" 并行 假设可以将一个任务分解成几个组件。幸运的话,你会发现可以将其中一些并行解决。例如: - 准备报告数据(计算、数据聚合…) - 应用样式规则 - 打印报告 可以让多个报告同时执行所有操作:一个报告正处在准备阶段,同时另一个报告已经开始打印,等等。这种方法并不新鲜。早在 60 年前批量数据处理技术出现时,它就开始发挥作用了。虽然这不是一个新的概念,但是非常有用。然而,只有当所有子任务的执行时间具有可比性时,才会实现显著的加速效果,实际情况却并非总是如此。 ### "水平" 并行 当任务的操作顺序可以按任意顺序执行并迭代时,它们可以同时执行。例如: - 全局范围内的上下文搜索: - 把 Global 分解成多个部分($order 作为首个索引). - 分别对其进行搜索. - 合成搜索结果. - 通过套接字或 ECP 将 Global 传输到另一台服务器: - 把 Global 分解成几个部分. - 分别进行传输. 这些任务具有以下共同特点: - 相同的子任务处理过程(包括共享相同的参数), - 最终结果的正确性不受子任务的执行顺序影响, - 生成结果报告的过程中不需要任何资源密集型操作,因此仅在此过程中子任务和“父”任务之间存在弱连接。 这些简单的示例表明,水平并行在数据转换任务中是常用到的,事实也的确如此。在接下来的内容中,我们将重点关注此类并行处理。 ## "水平" 并行 ### 方法之一:MapReduce MapReduce 是由谷歌引入的一种分布式计算模型。它在处理大量信息的同时也会执行此类操作。目前流行的开源项目构建在 [Apache Hadoop](https://ru.bmstu.wiki/Apache_Hadoop)和[Mahout](https:// ru.bmstu.wiki/apache_mahout) 的组合之上。 使用该模型的基本步骤:[映射](https://ru.bmstu.wiki/index.php?title=Map&action=edit&redlink=1)(在处理程序之间分配任务)、实际处理和[归约](https://ru.bmstu.wiki/index.php?title=Reduce&action=edit&redlink=1)(合并处理结果)。 对此感兴趣的读者如果想了解更多信息,我推荐 Timur Safin 的系列文章,他在[《Caché MapReduce——大数据和 MapReduce 概念简介》(第一部分)](https://community.intersystems.com/post/cach%C3%A9-mapreduce-introduction-bigdata-and-mapreduce-concept)中介绍了在 IRIS/Caché中创建MapReduce 工具的方法。 请注意,因为 IRIS 具有将数据快速写入数据库的"先天能力",所以归约这一步通常是微不足道的,类似 [WordCount 分布式版本](https://community.intersystems.com/post/cach%C3%A9-mapreduce-putting-it-all-together-%E2%80%93-wordcount-example-part-iii#comment-14196)中的情况。在处理数据库转换任务时,可能完全没有必要进行这一步。例如,使用并行处理程序将一个大型的 Global 移动到单独的数据库,则不需要任何其他操作。 ### 需要多少台服务器? 并行计算模型的创建者(例如 MapReduce)通常将其扩展到多个服务器,即所谓的数据处理节点,但是在数据库转换任务中,通常一个这样的节点就足够了。事实上,连接多个处理节点(例如,通过企业缓存协议(ECP))是没有意义的,因为数据转换所需的 CPU 负载相对较小——这里不用考虑处理过程中的数据量。在这种情况下,初始数据仅使用一次,也就意味着无法通过分布式缓存带来任何性能提升。 经验表明,比较方便的做法是使用两个角色不对称的服务器。下面稍微进行一下简化: - 将源数据库安装在一台服务器(*源数据库*)上。 - 将转换后的数据库安装在第二台服务器(*目标数据库*)上。 - 只在其中一台服务器上配置水平并行数据处理;此服务器上的操作进程作为*主进程*执行。 - 相应的,在第二台服务器上运行的进程作为*从属进程*;在使用 ECP 时,这些是 DBMS 系统进程(ECPSrvR、ECPSrvW 和 ECPWork),而当使用面向套接字的数据传输机制时,这些是TCP 连接的子进程。 可以说,这种分配任务的方法结合了水平并行(用于在主服务器内分配负载)和垂直并行(用于在主服务器和从属服务器之间分配“职责”)。 ## 任务和工具 让我们思考一下最普通的数据库转换任务:将全部或部分数据从源数据库传输到目标数据库,同时可能对 Global 执行某种重新编码(可以是编码更改、排序规则的更改等等)。在这种情况下,新旧数据库是保存在本地的不同数据库服务器上的。下面列出的是架构师和开发人员需要解决的子任务: 1. 给服务器分配角色。 2. 选择数据传输机制。 3. 选择 Global 转移策略。 4. 选择在多个进程之间分配任务的工具。 接下来我们逐个进行分析。 ### 给服务器分配角色 众所周知,即使 IRIS 以 Unicode 方式安装,它也可以挂载 8 位数据库(本地和远程)。但反之则不行:8 位版本的 IRIS 无法支持 Unicode 数据库,否则会出现错误。在决定将哪个服务器(源服务器或目标服务器)作为主服务器时,必须考虑到数据转换过程中字符编码是否发生了更改。然而,想要决定最终的解决方案,还需要考虑下一个任务,那就是: ### 选择数据传输机制 你有以下几个选项: 1. 如果两台服务器上的许可证和 DBMS 版本均支持 ECP,则应选择 ECP 作为传输机制。 2. 如果不支持,最简单的解决方案就是在目标服务器上本地处理两个数据库(源数据库和目标数据库)。这时必须利用任何可用的文件传输工具将源数据库文件复制到适当的服务器。当然,这个过程将占用额外的时间(通过网络复制数据库文件)和空间(存储数据库文件的副本)。 3. 为了(至少)避免把时间浪费在复制文件上,你可以通过 TCP 套接字机制实现服务器进程之间的数据交换。这种方法支持以下情况: - 由于某些原因无法使用 ECP,例如,为源数据库和目标数据库提供服务的 DBMS 版本不兼容(比如源 DBMS 安装的是非常旧的版本), - 或者:用户无法停止在源系统上工作,则源数据库在传输过程中发生的数据修改必须反映在目标数据库中。 在选择方法时,我的优先级非常明确:如果 ECP 可用,并且在传输期间源数据库保持静态,则选择方法 1;如果 ECP 不可用,但数据库保持静态,则选择方法 2;如果修改了源数据库,则选择方法 3。结合这些情况及主服务器的选择条件,我们可以生成如下可能性矩阵: | **传输期间源数据库是静态的吗?** | **ECP 协议是否可用?** | **源数据库的位置** | **主系统** | | --- | --- | --- | --- | | 是 | 是 | 目标系统远程 | 目标 | | 是 | 否 | 目标系统本地(副本) | 目标 | | 否 | 不重要,因为我们将使用TCP 套接字机制传输数据. | 源系统本地(原始) | 源| ### 选择 Global 转移策略 乍一看,似乎可以简单地通过读取全局目录逐个传递 Global。但是,同一个数据库中的Global 的大小可能相差很大:我最近遇到的一个生产数据库中的 Global 的大小范围在 1MB -600GB 之间。假设我们有多工作进程(nWorkers)可供使用,并且至少有一个 Global(Globals)^Big 符合下面条件: ^Big 的大小 >(所有^ Globals 的大小)/ nWorkers 然后,无论分布式 Global 转移过程中的其他任务完成的多么顺利,最终分配给^Big 的处理任务将一直保持忙碌,并且可能在其他进程完成之后很久才能完成其任务。如果想要改善这种情况,你可以预先按照大小对 Global 进行排序,并从最大的 Global 开始处理。但是如果^Big的大小明显偏离所有 Global 的平均值(这是 MIS qMS 数据库的典型情况): ^Big 的大小 >>(所有^ Globals 的大小)/ nWorkers 这个策略不会提供太大的帮助,因为它必定会产生好几个小时的延迟。因此,需要将大型Global 拆分成多个部分,通过多个并行进程对其进行处理。我想强调的是,这个任务(列表中的第 3 项任务)是本文讨论的最难的任务,而且花费了我(而不是 CPU!)很多时间。 ### 选择在多个进程之间分配任务的工具 与并行处理机制进行交互的方式如下: - 创建一个后台工作进程池。 - 为这个后台工作进程池创建一个队列。 - 发起程序(我们称其为本地管理器)将工作单元放入队列(这是在步骤 3 中预先准备好的计划)。工作单元通常包括某类方法的名称和实际参数。 - 工作进程从队列中检索工作单元并执行处理,这里可以理解成调用了一个类方法,将实际参数传递给工作单元。 - 本地管理器在接收到队列中工作单元已处理完毕的确认信息后,将释放并按需结束这些工作进程。 幸运的是,IRIS 提供了一个非常适合该方案的、出色的并行处理引擎(可以通过%SYSTEM.WorkMgr 类实现)。我们将在运行的实例中应用改引擎,并在计划发表的系列文章中进行深入探讨。 在下一篇文章中,我将更加详细地阐述任务 3 的解决方案。 在第三篇文章中(如果大家对我的文章感兴趣的话),我将讨论任务 4 中的细微差别,包括%SYSTEM.WorkMgr 的局限性及其解决方案。
文章
Qiao Peng · 二月 6, 2021

InterSystems:技术支持和 DBMS 互操作性管理解决方案

在本文中,我们将讨论一个我每天都会使用的应用程序,当监控 InterSystems IRIS 平台上的应用程序和集成解决方案并查找所发生的错误时,我就会用到它。 在查找用来记录 InterSystems IRIS、Ensemble 和 Caché DBMS 中对象变化的解决方案时,我发现了一篇关于[使用宏进行日志记录](https://community.intersystems.com/post/logging-using-macros-intersystems-cach%C3%A9)的好文章。 受到该文章的启发,我对其介绍的项目进行了分叉,并做了相应调整以满足一些特定需求。 生成的解决方案以面板子类 %CSP.Util.Pane 的形式实现,它具有主命令窗口、“Run”(运行)按钮和已启用的命令配置。 该应用程序允许查看和编辑 global 数组、执行查询(包括 JDBC 和 ODBC)、通过电子邮件发送搜索结果(压缩的 XLS 文件)、查看和编辑对象,以及用几个简单图表来表示系统协议。 该 apptools-admin 应用程序基于 jQuery-UI、UiKit、chart.js 和 jsgrid.js。 欢迎查看[源代码](https://openexchange.intersystems.com/package/apptools-admin)。 ### 安装 仓库中详细介绍了所有安装方法。 但是,最简单的方法是使用包管理器命令: ``` zpm "install apptools-admin" [apptools-admin] Reload START [apptools-admin] Reload SUCCESS [apptools-admin] Module object refreshed. [apptools-admin] Validate START [apptools-admin] Validate SUCCESS [apptools-admin] Compile START [apptools-admin] Compile SUCCESS [apptools-admin] Activate START [apptools-admin] Configure START http://hp-msw:52773/apptools/apptools.core.LogInfo.cls http://hp-msw:52773/apptools/apptools.Tabs.PanelUikitPermissMatrx.cls?autoload=Matrix [apptools-admin] Configure SUCCESS [apptools-admin] Activate SUCCESS ``` 第一个建议链接必须在浏览器的地址字段中打开。 在加载的面板中输入 `?` ,然后按“Execute”(执行)按钮。 应用程序随后会显示命令示例。 ![](https://lh5.googleusercontent.com/Tsh6XG7TAcQJHcxWPFIWU8FK6rPFYhxzTvxtiKvjw_QAKxGicy_sJt0WhTcG8zBXNvkQzLlRQPTN4juAk8vOn3gyUXJREfgPs9rqUoM8) ### 命令 在面板中,您可以运行实用工具,查看和编辑 global,以及执行查询。 每次启动都保存在命名空间上下文的历史记录中,因此可以找到并重复。 在此上下文中,“启动”表示开始执行命令,命令表示我们在面板中输入的所有内容。 下面的屏幕截图显示了 global 数组 `^%apptools.History` 查看命令的示例 ![](https://lh4.googleusercontent.com/Viy-pXX3dVlNrfUX7SV4Alxb9pM3I-uDKAYgHRVJKP1hK9BuvkMIuP6oPfDNYrmJb-VTl8b12Fy61q63O-nH0FYG2u8zIeux2e-vvl1h) 如您所知,自动错误检测和通知可以由流行的解决方案(例如 Prometheus)处理。 但通常可以通过视觉评估错误的严重性。 我经常需要快速获取所有命名空间中的生产错误信息。 为此,我实现了一个实用工具: `##class(apptools.core.Production).FindAndDrawAllErr` 这会启动一个每日搜索请求,用于查找每个包含工作产品的命名空间中的错误,并允许通过快速转换到可视化跟踪来查看这些错误。 您可以在 apptools 面板中像运行其他任何程序一样运行此实用工具,只需加上 `xec` 前缀。 ![](https://lh3.googleusercontent.com/0olzck-lNvNLsCwBphoTWLwZdSZJrNpb3qbkul4WuuXD9NnMnwpXofCsay9FxVW8S4iWvZD7L3z-s5UrKpicBofeXUrHsAfeQrnkEU8C-fjXqcdV3dmVGBcZOtgnSuFxWAHI-2Dr) 所有有用命令都可以保存在作用域上下文的 global 扩展中,以便随时查找和重复。 ![](https://lh4.googleusercontent.com/qBRtuZL_gOFOZD92CQOr0-w-NH8PfpVhIpQZYZENmblg8_jpW-dN_pF7bKiPAcWjkE3Tew6pU0k0NsLelUE1KFcCd4Xhl3bF4SjNdtttUGqNq0_eW6GtTIiP9iBx7bjJ2UnAkrF8) ### Global apptools-admin 应用程序的很大一部分专门用于处理 global。 可以按倒序查看 global,还可以对链接和数据应用筛选。 显示的注释可以进行编辑或删除。 ![](https://lh4.googleusercontent.com/_FfwdGX_A11k4ue8vZ51_3qwuVvTJd8a0UgFqDPsRJICYuUGmcRMFjOxdG1sdHkLJR3Ea7m30BHSpx33wjDDCd5qVvN01ewWUefSfgNaTzA9Z9HK2iFdYmZZ9yLYuTlTSHFAGfqJ) 您可以在 global 名称后输入 `*` 通配符,以获得具有附加特征的 global 列表。 第二个 `*` 将添加一个新字段“Allocated MB”(已分配 MB)。 第三个将添加“Used MB”(已使用 MB)字段。 此语法解析为两个报告的结合,星号将通常较长的报告分成易管理的部分。 ![](https://lh6.googleusercontent.com/1osTx0tWcdQlteMHlFjIw3K6SEjH_3gO6EpTUEsfyPgR3_ns8LR3mMIPQGt31ToANPqx0fB_Fkjh6tc6WeUSwS9_8bYx5UgRjHnOkUF0o0izVz7dBB9eok2skmsCoWZbeB7gk_kY) 当您获取 global 列表形式的报告时(上面的屏幕截图中),可以点击活动链接来查看 global 本身。 还可以在管理门户中点击“`Permission`”(权限)字段中的 `R` 或 `W`,以标准方式查看和编辑 global。 通常,在调试项目时,对 global 的写操作用于记录变量和对象的状态。 为此,我使用特殊宏: `set $$$AppL("MSW","anyText")=$$$AppObJs(%request)` 在此示例中,`$$$AppL` 为一个带 `^log` 前缀的 glob 以及索引值中的日期和时间形成链接。 `$$$AppObJs` 是对象序列化宏。 ![](https://lh4.googleusercontent.com/AOTb2Axpzo_YlYNJacWM4k9RAdO0OmYlkYjnUtvEWM3Djc9VQL6NTuEo1mXR5m5K-PtHtsRVUXNwsd7lwkKjuicOvRCq5j2Mwx5P2eBN8lpyPiFacue4riVFkmakPidY5P5-Iyrw) 您可以在面板中查看协议 global,对象可以在窗口中以完全格式化的形式显示。 ### 查询 与 global 的使用几乎一样多的功能是查询。 通过输入命令形式的语句来运行此功能。 例如,可以执行一个 SQL 语句。 ![](https://lh3.googleusercontent.com/uPQs2IAuSpdORQXaxy_rlzSFmaB9RxKoiVWRGyLsG_tthobEpxU8uBunOxOTi695q9yDCHr0Xjez8IE-U8HKWKOzpvczDmmgaFrcmHfCpo6hMXsxJCP05LtdeohTiTrrooYuSRyh) 还可以将结果保存在 global `^mtempSQLGN` 中。 ![](https://lh4.googleusercontent.com/HE44MxizdxfluYQyuEvEs1k7vmSNganzvoxPWTGfYnjJwgYWD7u9fBlCmHUFT2LOPzfLp8vBC23yJyDDYvnMZU7gwIoJjKaVMhv5WQ8Da2-_F-NrNdjpcYyd4V0BakEiRCcrbejZ) 随后,global 中保存的结果可以显示在面板中。 ![[](https://lh3.googleusercontent.com/yJVXXpPBZMsT-eXI0FCaWs6f7YvWpMH4zBIKAv-ejtpCdAxqK8fSh3YEy_IbF-aPv9ijRLZXcgy026xLLEAS449CtVjzeKiv2coQa9eK7OmyIbCFOs7pLxJa7Trw525xO3DJFsMH) ### 将报告转换为 Excel 格式 标准管理门户缺少的一项功能是执行数据库 JDBC 或 ODBC 源中配置的查询,输出 XLS 格式的结果,然后将文件存档并通过电子邮件发送。 要在应用程序中实现此功能,只需在执行命令之前选中“Upload to Excel file”(上传到 Excel 文件)复选框。 这个功能为我的日常工作节省了很多时间,让我可以成功地将现成模块融入到新的应用程序和集成解决方案中。 ![](https://lh4.googleusercontent.com/LhyeRllHAL6q-rBiRNbCAgGOflKF8OZjomLMCjVapJ2qbvhouPS44dIHmbwt4I3-LmADhgaSNPg-u57am73bcdNGTH97rWtdL1FEmXHI5O9eQYyTBINjidT2H8TGIrXIc6kt4MnV) 要启用此功能,首先需要配置服务器上用于创建文件的路径、用户凭据以及邮件服务器。 为此,又需要编辑全局程序设置 `^%apptools.Setting` 的节点。 ![](https://lh4.googleusercontent.com/cTDe7pUN7bhHYiweuWbdL0bXsF98UoVCPsyLt84xlp-vCEH5edjvTgxiNfPIZbKRnCGpUk1m8mr0aPKHFMs0JdIDdwqS53wCF_997Z3KrRrBqv6jKCam0zlPkklC_YTxm8gRXhPb) ### 全局保存报告 通常,您需要将报告执行的结果保存到 global。 为此,可以使用以下程序: | | 函数 | | -------- | -------------------------------------- | | 对于 JDBC: | ##class(apptools.core.sys).SqlToDSN | | 对于 ODBC: | ##class(apptools.core.sys).SaveGateway | | 对于 SQL: | ##class(apptools.core.sys).SaveSQL | | 对于查询: | ##class(apptools.core.sys).SaveQuery | 例如,使用 `##class(apptools.core.sys).SaveQuery` 函数,将查询 `%SYSTEM.License:Counts` 的结果保存到 global `^mtempGN` 中。 ![](https://lh5.googleusercontent.com/VTwoteSkKE0MRg00CojD8HCpcK7CNAr8wAVldyVRp3dweYbXampTmhfAkwdIqGdj6H3zkJQ4_qdnCugQkkdpkga1hbXCghSHyZ5pIOufqwu5vcEv9YF3zdE__AwHaPN-5DeK2t9k) 然后可以使用以下命令在面板中显示已保存的内容: `result ^mtempGN("%SYSTEM.License:Counts", 0)` https://lh5.googleusercontent.com/KCIekwZw3guq79GWxVdHYdAbWQc4u97-dr-hWT26lYE2oEzUTSkwCE4ki1zvNqRFBg6dKQshSqcy3YSgUbjFKgX3v7Ecpa5Bm_NEQuZhP8Fn8p1gzrmAdTR-Cg9jBeVcNWGukW3a ### 增强功能模块 还有什么简化和自动化了我的工作? 就是让我能够在形成查询字符串时执行自定义模块的更改。 我可以将新功能即时嵌入到报告中,例如用于对数据执行其他操作的活动链接。 让我们看一些示例。 我们使用以下函数在浏览器中显示查询结果: `##class(apptools.core.LogInfoPane).DrawSQL` ![](https://lh3.googleusercontent.com/2s0tgxOgbOBLy-Pt1e8bx_gKJWNe5YQ6AWLRUCU02TcpTiUscKYeoBEce2qdzCGlbAPzIukRn5EuJ9jwu8eATPCH13zoR8A2fQoAWZfx3RpieD_8rACgikcCZpcIoAIofxlzv2mT) 让我们将字标记函数 `##class(apptools.core.LogInfo)`.MarkRed 添加到参数 5 中。 ![](https://lh6.googleusercontent.com/OyotzU3vmjoXw_MzA6amZbpPlpbL-li71OH5JRw7sAfiVoEsAvi8wSfY588kzdyXTURtGtinj0WvIKDhNLGyy50BD40E7NEQSpNv2Iv85lQisJaMBquvheuXVrMravp6OlNxkcqI) 同样,可以为输出补充其他功能,例如,活动链接或工具提示。 本解决方案中的 global 编辑器根据同样的原理实现。 以下是以表格形式输出 global 和查询的函数列表: | | 函数 | | ------------- | ----------------------------------------------------------------------------- | | 对于 global: | ##class(apptools.core.LogInfoPane).DrawArray("^mtempSQLGN") | | 对于 SQL: | ##class(apptools.core.LogInfoPane).DrawSQL("select * From %SYS.ProcessQuery") | | 对于查询: | ##class(apptools.core.LogInfoPane).DrawSQL("query %SYSTEM.License:Counts") | | 对于 global 结果: | ##class(apptools.core.LogInfoPane).DrawSQL("result ^mtempSQLGN") | 使用 apptools.core.Parameter 类 在安装了 apptools-admin 的实例的上下文中,此链接将在浏览器中打开 CSP 应用程序。 `http://localhost:52773/apptools/apptools.Form.Exp.cls?NSP=APP&SelClass=apptools.core.Parameter` 或在面板中选择活动链接。 ![](https://lh4.googleusercontent.com/dt3oFX7Aum3yuJ4lvOtmhUWqm55GyFPPRGbsW7phZWRAnnJkB5xE0CdD3ddFEnS0-5xzSD_ydNe2hXp8Eqk1R39aioTZunY7bymF4EkPfaukm86sfFb-YrQp5Mx_KOyU9sr9cGbR) 将加载 CSP 应用程序以编辑存储类的实例,在此示例中: `apptools.core.Parameter`。 ![](https://lh5.googleusercontent.com/OLXVridH04HDDbufXUp9kZ70h08ptXrRcvDRThemPEira4KANa2ECTVGUJm7nuc3crqAnerWcJMToyipqM4YZCcnwqWRVXbOFKN0ZakCvpqrpdMsQZ0yXtCBgUt8z2U_JOmKnSFF) ![](https://lh4.googleusercontent.com/8JO4JQRssC22LGhab6dZiG6PnD2NRYIQtYsY9zj-Z99IIHxVpekzsxfV3Pw04SgxEqto_JepTXcht6vBu17D834Z_7_Hh-Yr5GmXSOsI5axLf7vIHxUi-tmTwcJH9DFlomurpgCH) ### 通过表导航器创建 apptools.core.Parameter 在安装了 apptools-admin 的实例的上下文中,如果在浏览器中打开此链接: `http://localhost:52773/apptools/apptools.Form.Exp.cls?panel=AccordionExp&NSP=APP` 或在面板中选择活动链接。 ![](https://lh3.googleusercontent.com/5me2dJ5aItW6iixR4mBfVRMJHDZfXRnq_pkGrlmCtCTeKzsRx0MbopN0YcLdvEsoWs46Aqw_0fVJGk6L88AaFNWeajDgggpwYawRTbdUIhHRxWo7pFiv3dqj_JdO5wgmm_uZTL5_) 将加载 CSP 应用程序以导航存储类,并能够编辑它们。 ![](https://lh3.googleusercontent.com/TjtNmzFRS8fTOpsRU0XAXYCHYHNpenI9H1WsEPEtVz7bT2jhakKjsfdJ_inLXX-cBsu5PlKgSJjIS3VoHXD6dqzEm0PDrhy2eOPFT-BoHx6ToPB6Jio21lN1bloGk1xtdlRR7Gd-) ### 简单 CSP 应用程序的示例 在安装了 apptools-admin 的实例的上下文中,如果在浏览器中打开此链接: `http://localhost:52773/apptools/apptools.Tabs.PanelSample.cls` 或在面板中选择活动链接。 ![](https://lh3.googleusercontent.com/mqMOjz96bd2YmJdIQtdVYsZhYDFW73BMJtjQh2q1wzzKYrzE39kWGTd2-M0kpBQlxIT2bkv2V7o7ieIlyV7aU8XNF29oI3spIoLGJJAHOKppLrTVrrR2XwOJHAQgLXM3TEQPWGGj) 此示例还显示了编辑类实例 `apptools.core.Parameter` 的能力。 ![](https://lh4.googleusercontent.com/sFXN0QJJb1UuyNJPhykvDOJeOEWC3RrO7oV1dqYixKnPlgEDFJdBqj5bORhaXlftxvngbu-UdgCqvG2UEr7_hKUhjGtJk6jrDNgc43f7DwWCmuDnFubMuIcavHAh7Z1--R72Pf_Q) ### 图表 为了直观展示数据库的增长,应用程序提供了一个图表页面,显示每月测量的数据库大小。 该图表来源于 IRIS file.log(对于 Caché 则为 cconsole.log)中从当天向回“扩展”的记录。 程序会遍历协议,找到数据库扩展记录,并从当前数据库大小中减去增量的兆字节。 最终生成数据库增长的图表。 例如,下面的屏幕截图显示了 InterSystems IRIS 中通过协议文件形成的事件图。 ![](https://lh4.googleusercontent.com/EbO0ZVyJwj1EgKF9SR6BpKPyBERj3cNgK4ckrDrzVWVu35LUlQAINvsbArTJ946XQWBhDUzS_dm4m3ize-RM7EjyRLQkesaNvNQOvK8FuUGwKx_8gqYlCMvmC2Xy2ih0xgZKx_q-) 下面是另一个示例:系统中的事件时间表,基于系统协议 file.log (cconsole.log)。 ![](https://lh6.googleusercontent.com/s3Uz-F88rFnBWSCS5_m4vtCQL9kdS2dEL101oWtlfmmNpfjF1PgtPppI2GC1g3syXIr39X1dUBO0O-gC5mDXcT1k6xOkXrz19TeRqpRAWrNG_FL6kMoyAZqS2N7mIDjG2BKpPy_j) ### 总结 我们在本文中讨论的应用程序旨在帮助我执行日常任务。 它包括一组模块,您可以将它们用作自定义管理员工具的构建块。 如果您觉得它对您的工作有用,我会非常高兴。 欢迎将愿望和建议作为任务添加到项目[仓库](https://github.com/SergeyMi37/apptools-admin)。