搜索​​​​

清除过滤器
文章
姚 鑫 · 六月 26, 2021

第十九章 使用%XML.TextReader

# 第十九章 使用%XML.TextReader `%XML.TextReader`类提供了一种简单、容易的方法来读取可能直接映射到InterSystems IRIS对象,也可能不直接映射到InterSystems IRIS对象的任意XML文档。具体地说,该类提供了导航格式良好的XML文档并查看其中信息(元素、属性、注释、名称空间URI等)的方法。该类还基于`DTD`或`XML`架构提供完整的文档验证。但是,与`%XML.Reader`不同的是,`%XML.TextReader`不提供返回`DOM`的方法。如果需要DOM,请参阅前面的“将XML导入对象”一章。 **注意:使用的任何XML文档的XML声明都应该指明该文档的字符编码,并且文档应该按照声明的方式进行编码。如果未声明字符编码,InterSystems IRIS将使用前面的“输入和输出的字符编码”中描述的默认值。如果这些默认值不正确,请修改XML声明,使其指定实际使用的字符集。** # 创建文本阅读器`Text Reader`方法 要读取不一定与 IRIS对象类有任何关系的任意XML文档,可以调用`%XML.TextReader`类的方法,该类将打开文档并将其作为文本阅读器对象加载到临时存储中。文本阅读器对象包含一个可导航的节点树,每个节点都包含有关源文档的信息。然后,方法可以导航该文档并查找有关该文档的信息。对象的属性提供有关文档的信息,这些信息取决于在文档中的当前位置。如果存在验证错误,这些错误也可以作为树中的节点使用。 ## 整体结构 法应执行以下部分或全部操作: 1. 通过以下方法之一的第一个参数指定文档源: `Method`| `First Argument` ---|--- `ParseFile()` |文件名,带有完整路径。请注意,文件名和路径只能包含ASCII字符。 `ParseStream()`|流 `ParseString()`| 字符串 `ParseURL()`| URL **在任何情况下,源文档都必须是格式良好的XML文档;也就是说,它必须遵守XML语法的基本规则。这些方法中的每一个都返回一个状态(`$OK`或失败代码),以指示结果是否成功。可以使用常用机制测试状态;特别是可以使用`$System.Status.DisplayError(status)`查看错误消息的文本。** 对于这些方法中的每一个,如果该方法返回$OK,则它通过引用(其第二个参数)返回包含XML文档中的信息的文本阅读器对象。 其他参数允许控制实体解析、验证、找到哪些项等。这些内容将在本章后面的“解析方法的参数列表”中介绍。 2. 检查解析方法返回的状态,并在适当的情况下退出。 如果解析方法返回$OK,则有一个与源XML文档相对应的文本阅读器对象。可以导航此对象。 文档可能包含`“element”`、`“endelement”`、`“startprefixmapping”`等节点。 重要提示:在任何验证错误的情况下,文档包含“错误”或“警告”节点。 代码应该检查这些节点。 3. 使用以下实例方法之一开始读取文档。 - 使用`Read()`导航到文档的第一个节点。 - 使用`ReadStartElement()`导航到特定类型的第一个元素。 - 使用`MoveToContent()`导航到类型为`“chars”`的第一个节点。 4. 获取该节点感兴趣的属性的值(如果有的话)。可用的属性包括名称、值、深度等。 5. 根据需要继续在文档中导航并获取属性值。 如果当前节点是元素,则可以使用`MoveToAttributeIndex()`或`MoveToAttributeName()`方法将焦点移至该元素的属性。若要返回到元素(如果适用),请使用`MoveToElement()`。 6. 如果需要,可以使用`Rewind()`方法返回到文档的开头(第一个节点之前)。这是唯一可以在源代码中倒退的方法。 方法运行后,文本读取器对象将被销毁,所有相关的临时存储都将被清除。 ## 示例1 下面是一个简单的方法,它可以读取任何XML文件,并显示每个节点的序列号、类型、名称和值: ```java /// w ##class(PHA.TEST.Xml).WriteNodes("E:\temp\textReader.txt") ClassMethod WriteNodes(myfile As %String) { set status = ##class(%XML.TextReader).ParseFile(myfile,.textreader) //检查状态 if $$$ISERR(status) {do $System.Status.DisplayError(status) quit} //逐个节点遍历文档 while textreader.Read() { Write !, "Node ", textreader.seq, " is a(n) " Write textreader.NodeType," " If textreader.Name'="" { Write "named: ", textreader.Name } Else { Write "and has no name" } Write !, " path: ",textreader.Path If textreader.Value'="" { Write !, " value: ", textreader.Value } } q "" } ``` 此示例执行以下操作: 1. 它调用`ParseFile()`类方法。这将读取源文件,创建一个文本阅读器对象,并通过引用在变量doc中返回该对象。 2. 如果`ParseFile()`成功,则该方法然后调用`read()`方法来查找文档中的每个后续节点。 3. 对于每个节点,该方法写入包含节点序列号、节点类型、节点名称(如果有)、节点路径和节点值(如果有)的输出行。输出将写入当前设备。 以下示例源文档: ```xml yaoxin 1990-04-25 ``` 对于此源文档,前面的方法生成以下输出: ```java DHC-APP>w ##class(PHA.TEST.Xml).WriteNodes("E:\temp\textReader.txt") Node 1 is a(n) processinginstruction named: xml-stylesheet path: value: type="text/css" href="mystyles.css" Node 2 is a(n) element named: Root path: /Root Node 3 is a(n) startprefixmapping named: s01 path: /Root value: s01 http://www.root.org Node 4 is a(n) element named: s01:Person path: /Root/s01:Person Node 5 is a(n) element named: Name path: /Root/s01:Person/Name Node 6 is a(n) chars and has no name path: /Root/s01:Person/Name value: yaoxin Node 7 is a(n) endelement named: Name path: /Root/s01:Person/Name Node 8 is a(n) element named: DOB path: /Root/s01:Person/DOB Node 9 is a(n) chars and has no name path: /Root/s01:Person/DOB value: 1990-04-25 Node 10 is a(n) endelement named: DOB path: /Root/s01:Person/DOB Node 11 is a(n) endelement named: s01:Person path: /Root/s01:Person Node 12 is a(n) endprefixmapping named: s01 path: /Root value: s01 Node 13 is a(n) endelement named: Root path: /Root ``` 请注意,注释已被忽略;默认情况下,`%XML.TextReader`忽略注释。 ## Example 2 下面的示例读取一个XML文件并列出其中的每个元素 ```java /// w ##class(PHA.TEST.Xml).ShowElements("E:\temp\textReader.txt") ClassMethod ShowElements(myfile As %String) { set status = ##class(%XML.TextReader).ParseFile(myfile,.textreader) if $$$ISERR(status) {do $System.Status.DisplayError(status) quit} while textreader.Read() { if (textreader.NodeType = "element") { write textreader.Name,! } } q "" } ``` 此方法使用`NodeType`属性检查每个节点的类型。如果节点是元素,则该方法将其名称打印到当前设备。对于前面显示的XML源文档,此方法生成以下输出: ```java DHC-APP>w ##class(PHA.TEST.Xml).ShowElements("E:\temp\textReader.txt") Root s01:Person Name DOB ``` # 节点类型 文档的每个节点都是以下类型之一: 文本阅读器文档中的节点类型 Type| Description ---|--- `"attribute"` |XML属性。 `"chars"` |一组字符(如元素的内容)。`%XML.TextReader`类识别其他节点类型(`“CDATA”`、`“EntityReference”`和`“EndEntity”`),但自动将它们转换为“字符”。 `"comment"`| XML注释。 `"element"`|XML元素的开始。 `"endelement"`|XML元素的结束。 `"endprefixmapping"`| 声明名称空间的上下文的结束。 `"entity"`|XML实体。 `"error"`| 解析器发现的验证错误。 `"ignorablewhitespace"`| 混合内容模型中标记之间的空白。 `"processinginstruction"`|XML处理指令。 `"startprefixmapping"`|XML命名空间声明,它可能包括也可能不包括命名空间。 `"warning"`| 解析器发现验证警告。 请注意,XML元素由多个节点组成。例如,以下XML片段: ```xml Willeke,Clint B. 1925-10-01 ``` SAX解析器将此XML视为以下节点集: 文档节点示例 Node Number |Type of Node| Name of Node, If Any| Value of Node, If Any ---|---|---|--- 1 |element |Person 2| element |Name 3| chars || Willeke,Clint B. 4 |endelement| Name 5| element| DOB 6| chars || 1925-10-01 7| endelement| DOB 8| endelement| Person 例如,注意``元素被认为是三个节点:一个元素节点、一个字符节点和一个结束元素节点。还要注意,该元素的内容只能作为`chars`节点的值使用。
文章
姚 鑫 · 九月 23, 2022

第四十一章 使用多个 IRIS 实例(一)

# 第四十一章 使用多个 IRIS 实例(一) 可以在单个主机系统上安装和运行多个 `IRIS®` 数据平台实例。每个实例都是一个独特的、独立的 `IRIS` 环境。 # 管理 IRIS 实例 有许多方法可以连接和管理 `IRIS` 实例,它可能是安装在给定系统上的几种方法之一。两种最常用的方法如下: - 安装在 `Windows` 系统上的每个 `IRIS` 实例在系统托盘中都有自己的启动器,除其他选项外,还可以: - 通过打开管理门户、 `Terminal`和 `Studio` 开发者客户端连接到实例。 - 启动、停止和重新启动实例。 - 打开用户和开发人员文档。 从启动器中,还可以管理多个远程 `IRIS` 实例,包括但不限于运行远程备份、编辑配置设置以及创建和编译远程对象和例程。 - `iris command` 在操作系统命令行上执行 iris 命令可让管理访问 `IRIS` 实例,其中包括其他选项,可以: - 使用 `Terminal`连接到实例。 - 启动、停止和重新启动实例。 - 显示有关该实例以及系统上安装的其他实例的信息。 要在远程服务器上使用 `iris` 命令,请使用 `Telnet` 或 `SSH` 客户端;要将它与容器化实例一起使用,请在容器内使用它,或者使用 `docker exec` 命令从容器外部运行它。 # 连接到 `IRIS` 实例 `Terminal` 是一个命令行,可以在 `IRIS` 实例的任何命名空间中使用。使用命令 `iris terminal instname` 打开正在运行的实例的终端,其中 `instname` 是在安装时为实例指定的名称。容器化实例通常被命名为 `IRIS`。 使用在安装期间提供的密码或创建的帐户使用预定义的用户帐户之一登录。显示的提示指示登录命名空间,例如: ```java # iris terminal IRISHealth Node: intersystems2588, Instance: IRIS27 Username: admin Password: ******** USER> ``` 要退出终端并关闭窗口,请输入命令 `halt`。 当使用`docker exec` 命令打开容器化实例的终端时(如在部署和探索 `IRIS` 中使用 终端进行交互中所述),将自动以 `irisowner` 身份登录,无需进行身份验证。 在 `Windows` 系统上,必须从其位置( `IRIS` 实例的 `install-dir\bin` 目录)执行命令,或在命令中包含完整路径,例如 `c:\InterSystems\IRIS27\bin\iris terminal IRISHealth` .可以执行给定实例的二进制文件以连接到该实例或另一个;无论哪种方式,实例名称都是必需的。
文章
姚 鑫 · 二月 12, 2023

第七十四章 使用 irisstat 实用程序监控 IRIS - 查看 irisstat 输出

# 第七十四章 使用 irisstat 实用程序监控 IRIS - 查看 irisstat 输出 # 查看 `irisstat` 输出 可以立即查看 `irisstat` 数据(通过终端)或重定向到输出文件以供以后分析。查看数据的最常见方法是: 注意:当 `IRIS` 被强制关闭时,`irisstat` 会运行以捕获系统的当前状态。作为紧急关闭程序的一部分,输出被添加到消息日志中。 ## irisstat 文本文件 `irisstat` 报告可以重定向到文件而不是终端,如果想收集一组 `IRIS` 工具(诊断报告任务、`IRISHung` 脚本、`^SystemPerformance` 实用程序)未提供的一组 `irisstat` 选项,这可能很有用或者如果在运行这些工具时遇到问题。 ## 诊断报告任务 诊断报告任务会创建一个包含基本信息和高级信息的 HTML 日志文件,InterSystems 全球响应中心 (WRC) 可以使用该文件来解决系统问题。 注意:诊断报告任务不能在挂起的系统上运行;如果系统挂起,请参阅本附录中的 `IRISHung` 脚本。 ## IRISHung 脚本 `IRISHung` 脚本是一个操作系统工具,用于在 `IRIS` 实例挂起时收集系统数据。位于 `install-dir\bin` 目录中的脚本名称是特定于平台的,如下表中指定: Platform| Script name ---|--- `Microsoft Windows`| `IRISHung.cmd` `UNIX®/Linux` |`IRISHung.sh` `IRISHung` 脚本应以管理员权限运行。与诊断报告任务一样,`IRISHung` 脚本运行 `irisstat` 两次,间隔 `30` 秒,以防状态发生变化,并将报告与其他收集的数据一起打包到一个 `html` 文件中。从 `IRISHung` 获取的 `irisstat` 报告使用以下选项 ```java irisstat -e2 -f-1 -m-1 -n3 -j5 -g1 -L1 -u-1 -v1 -p-1 -c-1 -q1 -w2 -E-1 -N65535 ``` `IRISHung` 还运行仅使用 `-S2` 选项的第三个 `irisstat`,它将其写入一个单独的输出部分,称为“自诊断”。 `-S2` 选项导致可疑进程留下小型转储;因此,运行 `IRISHung` 可能会收集有关负责挂起的特定进程的信息,而简单地强制实例关闭不会收集此信息。 此外,`IRISHung` 生成的 `irisstat` 输出文件通常非常大,在这种情况下,它们被保存到单独的 `.txt` 文件中。请记住在收集输出时检查这些文件。 ## `^SystemPerformance Utility` `^SystemPerformance` 实用程序收集有关 `IRIS` 实例及其运行平台的详细性能数据。在 `IRIS` 内运行一段可配置的时间,在该时间间隔内收集样本,并在完成时生成报告。
文章
Michael Lei · 四月 13, 2022

用Globals 作为图数据库来存储和抽取图结构数据

这篇文章是对我的 iris-globals-graphDB 应用的介绍。在这篇文章中,我将演示如何在Python Flask Web 框架和PYVIS交互式网络可视化库的帮助下,将图形数据保存和抽取到InterSystems Globals中。 建议 阅读相关文档 使用 Globals 原生 SDK 介绍 PYVIS 互动式网络可视化库 第一步 : 通过使用Python 原生SDK建立与IRIS Globals的链接 #create and establish connection if not self.iris_connection: self.iris_connection = irisnative.createConnection("localhost", 1972, "USER", "superuser", "SYS") # Create an iris object self.iris_native = irisnative.createIris(self.iris_connection) return self.iris_native 第二步 : 使用 iris_native.set( ) 功能把数据保存到Globals 里 #import nodes data from csv file isdefined = self.iris_native.isDefined("^g1nodes") if isdefined == 0: with open("/opt/irisapp/misc/g1nodes.csv", newline='') as csvfile: reader = csv.DictReader(csvfile) for row in reader: self.iris_native.set(row["name"], "^g1nodes", row["id"]) #import edges data from csv file isdefined = self.iris_native.isDefined("^g1edges") if isdefined == 0: with open("/opt/irisapp/misc/g1edges.csv", newline='') as csvfile: reader = csv.DictReader(csvfile) counter = 0 for row in reader: counter = counter + 1 #Save data to globals self.iris_native.set(row["source"]+'-'+row["target"], "^g1edges", counter) 第三步: 使用iris_native.get() 功能把节点和边缘数据从Globals传递给PYVIS #Get nodes data for basic graph def get_g1nodes(self): iris = self.get_iris_native() leverl1_subscript_iter = iris.iterator("^g1nodes") result = [] # Iterate over all nodes forwards for level1_subscript, level1_value in leverl1_subscript_iter: #Get data from globals val = iris.get("^g1nodes",level1_subscript) element = {"id": level1_subscript, "label": val, "shape":"circle"} result.append(element) return result #Get edges data for basic graph def get_g1edges(self): iris = self.get_iris_native() leverl1_subscript_iter = iris.iterator("^g1edges") result = [] # Iterate over all nodes forwards for level1_subscript, level1_value in leverl1_subscript_iter: #Get data from globals val = iris.get("^g1edges",level1_subscript) element = {"from": int(val.rpartition('-')[0]), "to": int(val.rpartition('-')[2])} result.append(element) return result Step4: Use PYVIS Javascript to generate graph data <script type="text/javascript"> // initialize global variables. var edges; var nodes; var network; var container; var options, data; // This method is responsible for drawing the graph, returns the drawn network function drawGraph() { var container = document.getElementById('mynetwork'); let node = JSON.parse('{{ nodes | tojson }}'); let edge = JSON.parse('{{ edges | tojson }}'); // parsing and collecting nodes and edges from the python nodes = new vis.DataSet(node); edges = new vis.DataSet(edge); // adding nodes and edges to the graph data = {nodes: nodes, edges: edges}; var options = { "configure": { "enabled": true, "filter": [ "physics","nodes" ] }, "nodes": { "color": { "border": "rgba(233,180,56,1)", "background": "rgba(252,175,41,1)", "highlight": { "border": "rgba(38,137,233,1)", "background": "rgba(40,138,255,1)" }, "hover": { "border": "rgba(42,127,233,1)", "background": "rgba(42,126,255,1)" } }, "font": { "color": "rgba(255,255,255,1)" } }, "edges": { "color": { "inherit": true }, "smooth": { "enabled": false, "type": "continuous" } }, "interaction": { "dragNodes": true, "hideEdgesOnDrag": false, "hideNodesOnDrag": false, "navigationButtons": true, "hover": true }, "physics": { "barnesHut": { "avoidOverlap": 0, "centralGravity": 0.3, "damping": 0.09, "gravitationalConstant": -80000, "springConstant": 0.001, "springLength": 250 }, "enabled": true, "stabilization": { "enabled": true, "fit": true, "iterations": 1000, "onlyDynamicEdges": false, "updateInterval": 50 } } } // if this network requires displaying the configure window, // put it in its div options.configure["container"] = document.getElementById("config"); network = new vis.Network(container, data, options); return network; } drawGraph(); </script> 第五步: 从app.py 主文件调用上面的代码 #Mian route. (index) @app.route("/") def index(): #Establish connection and import data to globals irisglobal = IRISGLOBAL() irisglobal.import_g1_nodes_edges() irisglobal.import_g2_nodes_edges() #getting nodes data from globals nodes = irisglobal.get_g1nodes() #getting edges data from globals edges = irisglobal.get_g1edges() #To display graph with configuration pyvis = True return render_template('index.html', nodes = nodes,edges=edges,pyvis=pyvis) 下面是关于此项目的 介绍视频: 欢迎大家来我们的 Bilibili主页观看更多视频! 谢谢!
文章
姚 鑫 · 九月 30, 2021

第三十一章 SQL命令 DROP DATABASE

# 第三十一章 SQL命令 DROP DATABASE 删除数据库(命名空间)。 # 大纲 ```sql DROP DATABASE dbname [RETAIN_FILES] ``` ## 参数 - `dbname` - 要删除的数据库(命名空间)的名称。 - `RETAIN_FILES` - 可选-如果指定,则不会删除物理数据库文件(`IRIS.DAT`文件)。默认情况下,删除`.dat`文件以及命名空间和其他数据库实体。 # 描述 `DROP DATABASE`命令删除命名空间及其关联的数据库。 指定的`dbname`是包含相应数据库文件的命名空间和目录的名称。指定`dbname`作为标识符。命名空间名称不区分大小写。如果指定的`DBNAME`命名空间不存在, IRIS将发出`SQLCODE-340`错误。 `DROP DATABASE`命令是一个特权操作。 在使用`DROP DATABASE`之前,必须以`%Admin_Manage`资源的用户身份登录。 用户还必须拥有用于例程和全局数据库定义的资源的`READ`权限。 如果不这样做,将导致`SQLCODE -99`错误(权限冲突)。 使用`$SYSTEM.Security.Login()`方法为用户分配适当的权限: ```java DO $SYSTEM.Security.Login("_SYSTEM","SYS") &sql( ) ``` 必须具有`%Service_Login:Use`权限才能调用`$SYSTEM.Security.Login`方法。 不管权限如何,`DROP DATABASE`都不能用于删除系统命名空间。尝试这样做会导致`SQLCODE-342`错误。 `DROP DATABASE`不能用于删除当前正在使用或连接到的命名空间。尝试这样做会导致`SQLCODE-344`错误。 还可以使用管理门户删除命名空间。依次选择System Administration、Configuration、System Configuration、Namespaces以列出现有的`Namespace`。单击要删除的命名空间的删除按钮。 ## RETAIN_FILES 如果指定此选项,则保留物理文件结构;删除数据库及其关联的命名空间。执行此操作后,后续尝试使用`DBNAME`将导致以下结果: - `DROP DATABASE`不带`RETAIN_FILES`无法删除此物理文件结构。相反,它会导致`SQLCODE-340`错误(未找到数据库)。 - `DROP DATABASE WITH RETAIN_FILES`还会导致`SQLCODE-340`错误(找不到数据库)。 - `CREATE DATABASE`无法创建同名的新数据库。相反,它会导致`SQLCODE-341`错误(无法为数据库创建数据库文件)。 - 尝试使用此命名空间会导致``错误。 ## 服务器初始化和断开代码 服务器初始化代码和服务器断开代码可以通过`$SYSTEM.SQL.Util.SetOption("ServerInitCode",value)`和`$SYSTEM.SQL.Util.SetOption("ServerDisconnectCode",value)`方法分配给命名空间。 可以使用相应的`$SYSTEM.SQL.Util.GetOption()`方法选项来确定当前值。 使用`DROP DATABASE`或其他接口删除命名空间,将删除这些`Server Init Code`和`Server Disconnect Code`值。 因此,删除并重新创建名称空间需要重新指定这些值。 # 示例 ```sql CREATE DATABASE DocTestDB ON DIRECTORY 'c:\InterSystems\IRIS142\mgr\DocTestDB' ``` ```sql DROP DATABASE DocTestDB RETAIN_FILES ```
文章
姚 鑫 · 三月 30, 2021

第十四章 使用SQL Shell界面(一)

# 第十四章 使用SQL Shell界面(一) # 执行SQL的其他方式 可以使用`$SYSTEM.SQL.Execute()` 方法从Terminal命令行执行一行SQL代码,而无需调用SQL Shell。以下示例显示如何在终端提示下使用此方法: ```sql DHC-APP>SET result=$SYSTEM.SQL.Execute("SELECT TOP 5 name,dob,ssn FROM Sample.Person") DHC-APP>DO result.%Display() Name DOB SSN yaoxin 54536 111-11-1117 xiaoli 111-11-1111 姚鑫 63189 111-11-1112 姚鑫 63189 111-11-1113 姚鑫 50066 111-11-1114 5 Rows(s) Affected ``` 如果SQL语句包含错误,则`Execute()`方法成功完成;否则,该方法无效。 `%Display()`方法返回错误信息,例如: ```java USER>DO result.%Display() [SQLCODE: :] [%msg: < Field 'GAME' not found in the applicable tables^ SELECT TOP ? game ,>] 0 Rows Affected USER> ``` `Execute()`方法还提供了可选的`SelectMode`、`Dialect`和`ObjectSelectMode`参数。 InterSystems IRIS支持许多其他编写和执行SQL代码的方法 这些包括: - 嵌入式SQL:嵌入ObjectScript代码中的SQL代码。 - 动态SQL:使用`%SQL`。 从ObjectScript代码中执行SQL语句的语句类方法。 - 管理门户SQL接口:使用Execute Query接口从InterSystems IRIS管理门户执行动态SQL。 # 调用SQL Shell 可以使用`$SYSTEM.SQL.Shell()`方法在终端提示符中调用SQL Shell,如下所示: ```java DO $SYSTEM.SQL.Shell() ``` 或者,可以使用%SQL作为一个实例调用SQL Shell。 Shell类,如下所示: ```java DO ##class(%SQL.Shell).%Go("IRIS") ``` 或 ```java SET sqlsh=##class(%SQL.Shell).%New() DO sqlsh.%Go("IRIS") ``` 无论如何调用,SQL Shell都会返回SQL Shell提示符,如下所示: ```java [SQL]termprompt>> ``` 其中[SQL]是指在SQL Shell中,termprompt是配置的终端提示符,`>>`是指SQL命令行。 默认情况下,SQL Shell提示符如下所示:`[SQL]nsp>>`,其中`“nsp”`是当前命名空间的名称。 ```java DHC-APP>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. DHC-APP>> > 1>> 1>>SELECT TOP 5 name,dob,ssn FROM Sample.Person 2>> 2>>q DHC-APP>>q ``` 在这个提示符下,可以使用以下任一Shell模式: - 单行模式:在提示符下键入一行SQL代码。 结束SQL语句,按`“Enter”`。 默认情况下,这将准备并执行SQL代码(这称为立即执行模式)。 对于查询,结果集显示在终端屏幕上。 对于其他SQL语句,将在终端屏幕上显示SQLCODE和行数值。 - 多行模式:在提示符下按Enter。这使进入多行模式。可以键入多行SQL代码,每个新行提示均指示行号。 (空行不会增加行号。)要结束多行SQL语句,请键入GO并按Enter。默认情况下,这既准备并执行SQL代码。对于查询,结果集显示在终端屏幕上。对于其他SQL语句,SQLCODE和行计数值显示在终端屏幕上。 多行模式提供以下命令,可以在多行提示符下键入以下命令,然后按Enter:`L`或`LIST`列出到目前为止输入的所有SQL代码。 `C`或`CLEAR`删除到目前为止输入的所有SQL代码。 `C n`或`CLEAR n`(其中`n`是行号整数)以删除特定的SQL代码行。 `G`或`GO`准备和执行SQL代码,然后返回单行模式。 `Q`或`QUIT`删除到目前为止输入的所有SQL代码并返回单行模式。这些命令不区分大小写。发出命令不会增加下一个多行提示的行号。打`?`在多行提示符处列出了这些多行命令。 为了准备一条SQL语句,SQL Shell首先验证该语句,包括确认指定的表存在于当前名称空间中,并且指定的字段存在于表中。如果不是,它将显示适当的SQLCODE。 如果该语句有效,并且具有适当的特权,则SQL Shell会回显SQL语句,并为其分配一个序号。无论您是否更改名称空间和/或退出并重新进入SQL Shell,这些数字在终端会话期间都将按顺序分配。这些分配的语句编号允许重新调用以前的SQL语句,如下所述。 也可以使用`DO Shell^%apiSQL`.在终端提示下调用SQL Shell。 要列出所有可用的SQL Shell命令,请输入`?`。在SQL提示下。 要终止SQL Shell会话并返回到`Terminal`提示符,请在SQL提示符下输入`Q`或`QUIT`命令或`E`命令。 SQL Shell命令不区分大小写。 以下是使用默认参数设置的示例SQL Shell会话: ```java DHC-APP>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. DHC-APP>>SELECT TOP 5 Name,Home_State FROM Sample.Person ORDER BY Home_State 1. SELECT TOP 5 Name,Home_State FROM Sample.Person ORDER BY Home_State Name Home_State xiaoli 姚鑫 姚鑫 姚鑫 姚鑫 5 Rows(s) Affected statement prepare time(s)/globals/lines/disk: 0.0523s/45502/270281/2ms execute time(s)/globals/lines/disk: 0.0004s/225/2915/0ms --------------------------------------------------------------------------- DHC-APP>>q ``` 以下是使用默认参数设置的多行SQL Shell会话: ```java DHC-APP>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. DHC-APP>> > 1>>SELECT TOP 5 2>>Name,Home_State 3>>FROM Sample.Person 4>>ORDER BY Home_State 5>>GO 2. SELECT TOP 5 Name,Home_State FROM Sample.Person ORDER BY Home_State Name Home_State xiaoli 姚鑫 姚鑫 姚鑫 姚鑫 5 Rows(s) Affected statement prepare time(s)/globals/lines/disk: 0.0002s/18/1168/0ms execute time(s)/globals/lines/disk: 0.0003s/225/2886/0ms --------------------------------------------------------------------------- ``` ## GO命令 SQL Shell `GO`命令执行最新的SQL语句。在单行模式下,`GO`重新执行最近执行的SQL语句。在多行模式下,`GO`命令用于执行多行SQL语句并退出多行模式。单行模式下的后续`GO`将重新执行先前的多行SQL语句。 ## 输入参数 SQL Shell支持使用`“?”`输入参数的使用SQL语句中的字符。每次执行SQL语句时,系统都会提示指定这些输入参数的值。必须以与`“?”`相同的顺序指定这些值字符出现在SQL语句中:第一个提示为第一个`“?”`提供一个值,第二个提示为第二个`“?”`提供一个值,依此类推。 输入参数的数量没有限制。可以使用输入参数将值提供给`TOP`子句,`WHERE`子句,并将表达式提供给`SELECT`列表。不能使用输入参数将列名提供给`SELECT`列表。 可以将主机变量指定为输入参数值。在输入参数提示下,指定一个以冒号(:)开头的值。该值可以是公共变量,ObjectScript特殊变量,数字文字或表达式。然后,SQL Shell会提示“这是文字(Y / N)吗?”。在此提示下指定N(否)(或仅按Enter)意味着将输入值解析为主机变量。例如,`:myval`将被解析为局部变量myval的值; `:^ myval`将被解析为全局变量`^myval`的值; `:$HOROLOG`将被解析为`$HOROLOG`特殊变量的值; `:3`将被解析为数字3; `:10-3`将被解析为数字`7`。在此提示符下指定Y(是)表示将输入值(包括冒号)作为文字提供给输入参数。 ## 执行ObjectScript命令 在SQL Shell中,可能希望发出一个ObjectScript命令。例如,通过使用`SET $NAMESPACE`命令将InterSystems IRIS命名空间更改为包含要引用的SQL表或存储过程的命名空间。可以使用SQL Shell!命令或OBJ命令以发出由一个或多个ObjectScript命令组成的ObjectScript命令行。 (OBJ是OBJECTSCRIPT的缩写。)!,OBJ和OBJECTSCRIPT命令是同义词。以下示例显示了这些命令的用法: ```java %SYS>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. [SQL]%SYS>>! SET oldns=$NAMESPACE SET $NAMESPACE="USER" WRITE "changed the namespace" changed the namespace [SQL]USER>>OBJ SET $NAMESPACE=oldns WRITE "reverted to old namespace" reverted to old namespace [SQL]%SYS>> ``` OBJ命令之后的其余命令行被视为ObjectScript代码。 !之间不需要空格。和ObjectScript命令行。可以在SQL Shell单行模式或SQL Shell多行模式下指定OBJ命令。以下示例在USER名称空间中定义的表上执行SELECT查询: ```java %SYS>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. [SQL]%SYS>> > 1>>OBJ SET $NAMESPACE="USER" 1>>SELECT TOP 5 Name,Home_State 2>>FROM Sample.Person 3>>GO /* SQL query results */ [SQL]USER>> ``` 请注意,OBJ语句不会增加SQL行数。 在SQL Shell多行模式下,在返回行时将执行OBJ命令,但是直到指定`GO`才发出SQL语句。因此,以下示例在功能上与先前的示例相同: ```java %SYS>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. [SQL]%SYS>> > 1>>SELECT TOP 5 Name,Home_State 2>>FROM Sample.Person 3>>OBJ SET $NAMESPACE="USER" WRITE "changed namespace" changed namespace 3>>GO /* SQL query results */ [SQL]USER>> ``` 以下示例使用OBJ命令定义主机变量: ```java USER>DO $SYSTEM.SQL.Shell() SQL Command Line Shell ---------------------------------------------- The command prefix is currently set to: . Enter q to quit, ? for help. [SQL]USER>> > 1>>SELECT TOP :n Name,Home_State 2>>FROM Sample.Person 3>>OBJ SET n=5 3>>GO ``` ## 浏览命名空间 SQL Shell支持BROWSE命令,该命令显示在当前名称空间中定义或可从其访问的架构,表和视图。该显示包括多个级别的提示。要返回上一个提示级别,请在提示时按`Return`键。名称区分大小写。 1. 在SQL Shell提示符下键入BROWSE,以列出当前名称空间中的架构。 2. 在“架构:”提示下,按名称或编号选择一个架构。这将列出架构中的表和视图。 3. 在“表/视图:”提示下,按名称或编号选择一个表(T)或视图(V)。这将显示表信息,然后显示选项列表。 4. 在“选项:”提示下,按编号选择一个选项。可以使用此选项列出为表定义的字段或映射。 指定选项1(按名称表示的字段)或选项2(按数字表示的字段)以显示“Field:”提示。指定选项3(地图)以显示“Map:”提示。 5. 在`“Field:”`提示下,按数字或名称选择一个字段,或指定*以列出所有字段。这列出了详细的字段信息。 在`“Map:”`提示下,按数字或名称选择地图,或指定`*`列出所有Map。这列出了详细的Map信息。 ## CALL 命令 可以使用SQL Shell发出SQL `CALL`语句来调用SQL存储过程,如以下示例所示: ```java DHC-APP>>CALL Sample.PersonSets('G','NY') 3. CALL Sample.PersonSets('G','NY') Dumping result #1 Name DOB Spouse Gallant,Thelma Q. 45767 94 Gibbs,Mark S. 37331 13 Goldman,Will H. 59069 10 Gomez,Mo Q. 55626 55 Gore,Alfred M. 42991 13 Gore,Fred X. 32391 6 Grabscheid,Jocelyn B. 59676 79 7 Rows(s) Affected Dumping result #2 Name Age Home_City Home_State Chadbourne,Danielle G. 34 Pueblo NY Eastman,Clint G. 4 Miami NY Pape,Linda M. 71 Vail NY Peterson,Janice N. 49 Islip NY Schaefer,Jocelyn V. 93 Zanesville NY 5 Rows(s) Affected statement prepare time(s)/globals/lines/disk: 0.0043s/2153/15795/0ms execute time(s)/globals/lines/disk: 0.0015s/315/7829/0ms --------------------------------------------------------------------------- ``` 如果指定的存储过程在当前名称空间中不存在,则SQL Shell会发出`SQLCODE -428`错误。 如果指定的输入参数多于存储过程中定义的参数,则SQL Shell会发出`SQLCODE -370`错误。可以使用文字(`“字符串”`),主机变量(`:var`)和输入参数(`?`)的任意组合为存储过程指定参数值。 可以在`CALL`语句中使用主机变量,如以下示例所示: ```java [SQL]USER>>OBJ SET a="G",b="NY" [SQL]USER>>CALL Sample.PersonSets(:a,:b) ``` - 可以在`CALL`语句中使用输入参数(`“?”`字符),如以下示例所示: ```java [SQL]USER>>CALL Sample.PersonSets(?,?) ``` 当执行`CALL`语句时,SQL Shell会提示为每个输入参数提供一个值。 ## 执行SQL脚本文件 SQL Shell `RUN`命令执行一个SQL脚本文件。脚本文件的类型由`DIALECT`设置确定。 `DIALECT`的默认值为IRIS(InterSystems SQL)。
文章
姚 鑫 · 四月 14, 2021

第二章 定义和构建索引(二)

# 第二章 定义和构建索引(一) # 定义索引 ### 使用带有索引的Unique、PrimaryKey和IdKey关键字 与典型的SQL一样,InterSystems IRIS支持惟一键和主键的概念。 InterSystems IRIS还能够定义`IdKey`,它是类实例(表中的行)的唯一记录ID。 这些特性是通过`Unique`、`PrimaryKey`和`IdKey`关键字实现的: - `Unique` -在索引的属性列表中列出的属性上定义一个唯一的约束。 也就是说,只有这个属性(字段)的唯一数据值可以被索引。 唯一性是根据属性的排序来确定的。 例如,**如果属性排序是精确的,则字母大小写不同的值是唯一的; 如果属性排序是`SQLUPPER`,则字母大小写不同的值不是唯一的。** 但是,请注意,对于未定义的属性,不会检查索引的惟一性。 根据SQL标准,未定义的属性总是被视为唯一的。 - `PrimaryKey` -在索引的属性列表中列出的属性上定义一个主键约束。 - `IdKey` -定义一个唯一的约束,并指定哪些属性用于定义实例(行)的唯一标识。 `IdKey`总是具有精确的排序规则,即使是数据类型为`string`时也是如此。 这些关键字的语法出现在下面的例子中: ```java Class MyApp.SampleTable Extends %Persistent [DdlAllowed] { Property Prop1 As %String; Property Prop2 As %String; Property Prop3 As %String; Index Prop1IDX on Prop1 [ Unique ]; Index Prop2IDX on Prop2 [ PrimaryKey ]; Index Prop3IDX on Prop3 [ IdKey ]; } ``` **注意:`IdKey`、`PrimaryKey`和`Unique`关键字只在标准索引下有效。 不能将它们与位图或位片索引一起使用。** 同时指定`IdKey`和`PrimaryKey`关键字也是有效的语法,例如: ``` Index IDPKIDX on Prop4 [ IdKey, PrimaryKey ]; ``` 这个语法指定`IDPKIDX`索引既是类(表)的`IdKey`,也是它的主键。 这些关键字的所有其他组合都是多余的。 对于使用这些关键字之一定义的任何索引,都有一个方法允许打开类的实例,其中与索引关联的属性有特定的值; ### 定义SQL搜索索引 可以在表类定义中定义SQL搜索索引,如下所示: ```java Class Sample.TextBooks Extends %Persistent [DdlAllowed] { Property BookName As %String; Property SampleText As %String(MAXLEN=5000); Index NameIDX On BookName [ IdKey ]; Index SQLSrchIDXB On (SampleText) As %iFind.Index.Basic; Index SQLSrchIDXS On (SampleText) As %iFind.Index.Semantic; Index SQLSrchIDXA On (SampleText) As %iFind.Index.Analytic; } ``` ### 用索引存储数据 **可以使用index Data关键字指定一个或多个数据值的副本存储在一个索引中:** ```java Class Sample.Person Extends %Persistent [DdlAllowed] { Property Name As %String; Property SSN As %String(MAXLEN=20); Index NameIDX On Name [Data = Name]; } ``` 在本例中,索引`NameIDX`的下标是各种`Name`值的排序(大写)值。名称的实际值的副本存储在索引中。当通过SQL更改`Sample.Person`表或通过对象更改对应的`Sample.Person`类或其实例时,将维护这些副本。 在经常执行选择性(从许多行中选择一些行)或有序搜索(从许多列中返回一些列)的情况下,在索引中维护数据副本会很有帮助。 例如,考虑以下针对`Sample.Person`表的查询: SQL引擎可以通过读取`NameIDX`而从不读取表的主数据来决定完全满足此请求。 ![image](/sites/default/files/inline/images/1_34.png) **注意:不能使用位图索引存储数据值。** ### 索引null 如果一个索引字段的数据为`NULL`(没有数据存在),相应的索引使用索引`NULL`标记来表示这个值。 **默认情况下,索引空标记值为`-1E14`。** 使用索引空标记可以使空值排序在所有非空值之前。 `%Library.BigInt`数据类型存储小于`-1E14`的小负数。默认情况下,`%BigInt`索引空标记值为`-1E14`,因此与现有`BigInt`索引兼容。如果索引的`%BigInt`数据值可能包括这些极小的负数,则可以使用`INDEXNULLMARKER`属性参数更改特定字段的索引`NULL`标记值,作为特性定义的一部分,如下例所示: ```java Property ExtremeNums As %Library.BigInt(INDEXNULLMARKER = "-1E19"); ``` 还可以在数据类型类定义中更改索引`NULL`标记的默认值。 **此参数属性在IRIS里有,Cache里没有。** ### 索引集合 为属性编制索引时,放在索引中的值是整个已整理属性值。对于集合,可以通过将(`Elements`)或(`Key`)附加到属性名称来定义与集合的元素和键值相对应的索引属性。(元素)和(键)允许指定从单个属性值生成多个值,并对每个子值进行索引。当属性是集合时,`Elements`令牌通过值引用集合的元素,`Key`令牌通过位置引用它们。当元素和键都出现在单个索引定义中时,索引键值包括键和关联的元素值。 例如,假设有一个基于`Sample.Person`类的`FavoriteColors`属性的索引。对此属性集合中的项进行索引的最简单形式是以下任一种: ```java INDEX fcIDX1 ON (FavoriteColors(ELEMENTS)); ``` 或 ```java INDEX fcIDX2 ON (FavoriteColors(KEYS)); ``` 其中,`FavoriteColor(Elements)`是指`FavoriteColors`属性的元素,因为它是一个集合。一般形式是`PropertyName`(元素)或`PropertyName`(键),其中该集合的内容是定义为某个数据类型的列表或数组的属性中包含的一组元素)。 若要索引文本属性,可以创建一个由`PropertyNameBuildValueArray()`方法生成的索引值数组(在下一节中介绍)。与集合本身一样,(Elements)和(Key)语法对索引值数组有效。 如果属性集合被投影为数组,则索引必须遵守以下限制才能被投影到集合表。索引必须包括(键)。索引不能引用集合本身和对象ID值以外的任何属性。如果投影索引还定义了要存储在索引中的数据,则存储的数据属性也必须限制为集合和ID。否则,不会投影索引。此限制适用于投影为数组的集合属性上的索引;不适用于投影为列表的集合上的索引。 与集合的元素或键值对应的索引还可以具有所有标准索引功能,例如将数据与索引一起存储、特定于索引的排序规则等。 InterSystems SQL可以通过指定`FOR SOME%ELEMENT`谓词来使用集合索引。 ### 使用(Elements)和(Key)索引数据类型属性 为了索引数据类型属性,还可以使用`BuildValueArray()`方法创建索引值数组。此方法将属性值解析为键和元素的数组;它通过生成从与其关联的属性的值派生的元素值集合来实现这一点。使用`BuildValueArray()`创建索引值数组时,其结构适合索引。 `BuildValueArray()`方法的名称为`PropertyNameBuildValueArray()`,其签名为: ```java ClassMethod propertynameBuildValueArray(value, ByRef valueArray As %Library.String) As %Status ``` - `BuildValueArray()`方法的名称以组合方法的典型方式派生于属性名。 - 第一个参数是属性值。 - 第二个参数是通过引用传递的数组。 这是一个包含键-元素对的数组,键下标的数组等于元素。 - 该方法返回一`%Status` 值。 这个例子: ```java /// DescriptiveWords是一个以逗号分隔的单词字符串 Property DescriptiveWords As %String; /// 基于描述词的索引 Index dwIDX On DescriptiveWords(ELEMENTS); /// 方法的作用是:演示如何在属性的子值上建立索引。 /// /// (如果DescriptiveWords被定义为一个集合,则不需要此方法。) ClassMethod DescriptiveWordsBuildValueArray( Words As %Library.String = "", ByRef wordArray As %Library.String) As %Status { If Words '= "" { For tPointer = 1:1:$Length(Words,",") { Set tWord = $Piece(Words,",",tPointer) If tWord '= "" { Set wordArray(tPointer) = tWord } } } Else { Set wordArray("TODO") = "Enter keywords for this person" } Quit $$$OK } ``` 在本例中,`dwIDX`索引基于`DescriptiveWords`属性。 `DescriptiveWordsBuildValueArray()`方法接受由`Words`参数指定的值,基于该值创建一个索引值数组,并将其存储在`wordArray`中。 InterSystems IRIS在内部使用`BuildValueArray()`实现; 不调用此方法。 注意:没有必要将任何元素/键值建立在属性值的基础上。 唯一的建议是,每次向该方法传递给定值时,都创建相同的元素和键数组。 为各种实例的描述性词所属性设置值和检查这些值的属性涉及活动(如以下): ```java SAMPLES>SET empsalesoref = ##class(MyApp.Salesperson).%OpenId(3) SAMPLES>SET empsalesoref.DescriptiveWords = "Creative" SAMPLES>WRITE empsalesoref.%Save() 1 SAMPLES>SET empsalesoref = ##class(MyApp.Salesperson).%OpenId(4) SAMPLES>SET empsalesoref.DescriptiveWords = "Logical,Tall" SAMPLES>WRITE empsalesoref.%Save() 1 ``` 这 `sample index`内容,例如: DescriptiveWords(ELEMENTS) | ID | Data ---|---|--- " CREATIVE" |3 |"" " ENTER KEYWORDS FOR THIS PERSON"| 1 |"" " ENTER KEYWORDS FOR THIS PERSON"| 2| "" " LOGICAL" |4| "" " TALL"| 4| "" 注意:此表显示抽象中的索引内容。磁盘上的实际存储形式可能会有所变化。 ### 将数组(元素)上的索引投影到子表 要在嵌入式对象中索引属性,需要在引用该嵌入式对象的持久化类中创建索引。 属性名必须指定表(`%Persistent`类)中的引用字段的名称和嵌入对象(`%SerialObject`)中的属性的名称,如下面的示例所示: ```java Class Sample.Person Extends (%Persistent) [ DdlAllowed ] { Property Name As %String(MAXLEN=50); Property Home As Sample.Address; Index StateInx On Home.State; } ``` 此处`Home`是`Sample.Person`中引用嵌入对象`Sample.Address`的属性,该对象包含`State`属性,如下例所示: ```java Class Sample.Address Extends (%SerialObject) { Property Street As %String; Property City As %String; Property State As %String; Property PostalCode As %String; } ``` **只有与持久类属性引用相关联的嵌入对象的实例中的数据值被索引。不能直接索引`%SerialObject`属性**。`%Library.SerialObject`(以及`%SerialObject`的所有未显式定义`SqlCategory`的子类)的`SqlCategory`为字符串。 还可以使用`SQL CREATE INDEX`语句在嵌入式对象属性上定义索引,如下例所示: ```sql CREATE INDEX StateIdx ON TABLE Sample.Person (Home_State) ``` ### 类中定义的索引注释 当在类定义中使用索引时,需要记住以下几点: - **索引定义仅从主(第一个)超类继承。** - **如果使用Studio添加(或删除)数据库中存储数据的类的索引定义,则必须使用“构建索引”中描述的过程之一来手动填充索引。** ## 使用DDL定义索引 如果你使用DDL语句来定义表,也可以使用以下DDL命令来创建和删除索引: - `CREATE INDEX` - `DROP INDEX` `DDL index`命令执行以下操作: 1. 它们更新在其上添加或删除索引的相应类和表定义。 重新编译修改后的类定义。 2. 它们根据需要在数据库中添加或删除索引数据:`CREATE index`命令使用当前存储在数据库中的数据填充索引。 类似地,`DROP INDEX`命令从数据库中删除索引数据(即实际索引)。
文章
Michael Lei · 六月 23, 2021

最低限度的监控和警报解决方案

InterSystems 数据平台包括了用于系统监视和警报的实用程序及工具,但对于不熟悉构建于 InterSystems 数据平台(又名 Caché)的解决方案的系统管理员来说,他们需要知道从何处下手以及需要配置什么。 本指南以在线文档和开发者社区帖子为参考,介绍了实现最低限度的监视和警报解决方案的途径,以及如何启用和配置以下组件: 1. **Caché Monitor:**扫描控制台日志并发送电子邮件警报。 2. **System Monitor:**监视系统状态和资源,根据固定参数生成通知(警报和警告),同时跟踪整体系统运行状况。 3. **Health Monitor:**对主要的系统和用户定义指标进行采样,并将它们与用户可配置的参数和既定的标准值进行比较,在样本超过适用或学习的阈值时生成通知。 4. **History Monitor:**维护性能指标和系统使用情况指标的历史数据库。 5. **pButtons:**每天按计划收集操作系统指标和 Caché 指标。 请记住,本指南是最低配置,所包含的工具灵活且可扩展,因此可在需要时提供更多功能。 本指南跳过了文档,让您直接上手。 您需要更深入地研究文档才能充分利用监视工具,同时,请考虑将本指南作为启动和运行的速查表。 ---- # 1. Caché Monitor 控制台日志 `(install-directory/mgr/cconsole.log)` 必须被监视,可以通过第三方工具扫描日志文件,或者像我们这样使用附带的 Caché Monitor 实用工具将警报发送到一个电子邮件地址。 控制台日志是其他监视工具(包括 Caché System Monitor 和 Caché Health Monitor)用于编写警报和通知的中央存储库。 > 至少将 Caché Monitor 配置为向一个电子邮件发送警报。 使用 ^MONMGR 实用工具管理 Caché Monitor。 ## Caché Monitor 基本设置 Caché Monitor 扫描控制台日志,并根据可配置的消息严重级别生成通知。 通知通过电子邮件发送到您配置的收件人列表。 默认扫描周期为每 10 秒一次,但可以更改。 > 提示:将 Caché Monitor 警报严重级别配置为 1(警告、严重和致命条目)。 如果您发现收到的警报太多,可以降回到警报级别 2(严重和致命条目)。 当 60 秒内有一系列条目来自一个给定进程时,只会针对第一个条目生成通知,然后暂停一小时。 因此,当出现问题时,必须进行调查。 因为没有新消息并不表示事件已过去。 此规则的例外是 [Caché Monitor 错误和陷阱](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_monitor#GCM_monitor_errors)中列出的控制台日志条目,会针对其中所有条目生成通知。 [有关完整的配置详细信息,请参见 ^MONMGR 的在线文档。](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_monitor#GCM_monitor_errors) ## Caché Monitor 速查表 启用 Caché Monitor 不需要很多操作。 确保 Monitor 已启动,然后设置电子邮件选项。 %SYS>d ^MONMGR 1) Start/Stop/Update MONITOR 2) Manage MONITOR Options 3) Exit Option? **1** 1) Update MONITOR 2) Halt MONITOR 3) Start MONITOR 4) Reset Alerts 5) Exit Option? **3** Starting MONITOR... MONITOR started 1) Update MONITOR 2) Halt MONITOR 3) Start MONITOR 4) Reset Alerts 5) Exit Option? **** 设置警报严重级别。 1) Start/Stop/Update MONITOR 2) Manage MONITOR Options 3) Exit Option? **2** 1) Set Monitor Interval 2) Set Alert Level 3) Manage Email Options 4) Exit Option? **2** Alert on Severity (1=warning,2=severe,3=fatal)? 2 => **1** 设置电子邮件选项,您可能需要联系 IT 部门以获取电子邮件服务器的地址。 任何有效的电子邮件地址都应该可用。 1) Set Monitor Interval 2) Set Alert Level 3) Manage Email Options 4) Exit Option? **3** 1) Enable/Disable Email 2) Set Sender 3) Set Server 4) Manage Recipients 5) Set Authentication 6) Test Email 7) Exit Option? 确保在设置后测试电子邮件(选项 6)。 ## Caché Monitor 示例 Caché System Monitor 针对高 CPU 利用率生成了一个严重级别为 2 的条目,该条目已发送到 cconsole.log: 03/07/18-11:44:50:578 (4410) 2 [SYSTEM MONITOR] CPUusage Alert: CPUusage = 92, 95, 98 (Max value is 85). 同时也向 Caché Monitor 电子邮件收件人发送了一封电子邮件,其内容与 console.log 相同,主题行为: [CACHE SEVERE ERROR yourserver.name.com:instancename] [SYSTEM MONITOR] CPUusage Alert: CPUusage = 92, 95, 98 (Max value is 85). ## Caché Monitor 更多提示 在开发者社区的另一篇文章的评论中,Aric West 提示可以在发件人电子邮件中嵌入更多信息,例如,不要只设置一个有效的电子邮件,而是将发件人或收件人设置为:"某个名字" \ ---- # Caché System Monitor 工具 Caché System Monitor 是一系列监视工具的汇总,通过 `^%SYSMONMGR` 实用工具进行配置。 如简介中所述,为实现最低限度的监视解决方案,我们将配置: - System Monitor - Health Monitor - History Monitor 顺带说一下,是的,名称 _System Monitor_ 很令人烦恼地重载了其父名称 _Caché System Monitor_。 Caché System Monitor 和 Health Monitor 通知和警报会发送到控制台日志,使 Caché Monitor(在上一节中设置)可以在事件发生时生成电子邮件。 [有关 Caché System Monitor 的所有深入详细信息,请参见在线文档。](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_healthmon) ---- **警告说明:**您还将在 ^%SYSMONMGR 菜单中看到 **Application Monitor**。 本指南中不会配置 Application Monitor。 本指南中介绍的工具和实用程序对系统性能的影响可以忽略不计,然而 Application Monitor 有一些类是此规则的例外。 [有关详细信息,请参见 ^PERFMON 实用工具的文档](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_perfmon)。 如果您使用 Application Monitor,则必须先在非生产系统上测试,因为运行任何时长的 ^PERFMON 都可能对性能产生重大影响。 ---- # 2. System Monitor 根据文档:“System Monitor 对重要的系统状态和资源使用指标(例如 ECP 连接的状态和使用中的锁表的百分比)进行采样,并根据固定状态和阈值生成通知(警报、警告和‘状态正常’消息)”。 [文档中有 System Monitor 状态和资源指标](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_healthmon_sysmon_alerts)的列表。 例如:日志空间(日志目录中的可用空间): - 少于 250 MB = _警告_ - 少于 50 MB = _警报_ - 警告/警报后大于 250 MB = _正常_ ## System Monitor 基本设置 System Monitor 警报和警告会写入控制台日志,因此请确保 Caché Monitor 设置为发送电子邮件警报(上一节)。 使用 ^SYSMONMGR 实用工具管理 System Monitor。 默认情况下,当实例运行时,System Monitor 也一直运行;可以使用 ^%SYSMONMGR 将其停止,但是当实例下次启动时,它会自动再次启动。 默认情况下,System Monitor 具有以下可以更改的设置: - 每 30 秒获取一次传感器指标。 - 仅将警报、警告和消息写入 System Monitor 日志。 System Monitor 还维护单一整体系统运行状况状态,当运行 `ccontrol list` 等命令时可以查询或使用该状态: - 绿色(正常) - 黄色(警告) - 红色(警报) ### System Monitor 速查表 对于最低限度的监视解决方案,实际上无需任何操作,因为当实例运行时,它也一直运行。 ---- # 3. Health Monitor 根据文档:“Caché Health Monitor 通过在特定期间对一系列关键指标的值进行采样,并将这些值与配置的指标参数和这些期间的既定标准值进行比较,来监视正在运行的 Caché 实例;如果采样值过高,Health Monitor 将生成警报或警告。 例如,根据配置的 CPU 使用率最大值或者在星期一上午 9:00 至 11:30 期间采集的标准 CPU 使用率样本,如果 Health Monitor 在星期一上午 10:15 采样的 CPU 使用率过高,Health Monitor 将生成通知。” [Health Monitor 对 41 个系统传感器进行采样,文档中给出了列表和默认值。](http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=GCM_healthmon#GCM_healthmon_overview_api_sensors) Health Monitor 警报(严重级别 2)和警告(严重级别 1)将写入控制台日志。 Health Monitor 生成: - 警报,如果在一个期间内传感器的三次连续读数大于传感器最大值。 - 警告,如果在一个期间内传感器的五次连续读数大于传感器警告值。 对于为最大值或警告值设置了条目的传感器,即使 Health Monitor 本身未启用,也会立即生成警报。 例如,为 CPU 配置的最大值为 85,警告值为 75,所以当连续 5 次的 CPU 利用率测量值超过 75% 时,会将以下通知发送到控制台日志: 1 [SYSTEM MONITOR] CPUusage Warning: CPUusage = 83 ( Warnvalue is 75). 其他传感器需要收集足够长时间的指标才能创建_图表_。 需要图表来评估指标的平均值,从而得出标准偏差 (sigma),以便在值超出正常范围时发出警报。 在一个_期间_内收集指标。 有 63 个标准期间,一个期间示例是星期一上午 9:00 至 11:30。 期间可以更改。 ## Health Monitor 基本设置 > Health Monitor 不会自动启动,需要使用 ^%SYSMONMGR 中的设置来启用它。 默认情况下,Health Monitor 在 Caché 启动后等待 10 分钟,以便系统达到正常运行状态,如果需要,可以更改此时间。 Caché Health Monitor 传感器对象带有默认值。 例如,如上文所述,_CPUPct_(系统 CPU 使用率百分比)的默认值为:基础值 50,最大值 90,警告值 80。 您可能更保守一些,并想要更改这些值,使用 ^%SYSMONMGR 可以更改这些值,例如,最大值 85,警告值 70。 现在,当 CPU 使用率达到 99% 时,我们会看到: 2 [SYSTEM MONITOR] CPUusage Alert: CPUusage = 99, 99, 99 (Max value is 85). ## Health Monitor 速查表 该速查表相当长,显示在总结后面。 ---- # 4. History Monitor [David Loveluck 在社区上有一个非常好的帖子。](https://community.intersystems.com/post/apm-using-cach%C3%A9-history-monitor)按照该帖中的说明启动 History Monitor,开始收集和评估指标。 ---- # 5. pButtons pButtons 实用工具可根据其创建的日志文件生成可读的 HTML 性能报告,其中包含操作系统和 Caché 指标。 pButtons 输出的性能指标可以被提取、绘图和评估。 例如,一天中 CPU 利用率或 Caché 数据库访问量的图表。 每天 24 小时运行 pButtons 收集是一种简单但至关重要的方法,用于收集指标以进行故障排除。 pButtons 对于趋势分析也非常有用。 以下社区文章详细介绍了 pButtons 以及如何将其计划为每天运行:[InterSystems 数据平台和性能 – 第 1 部分](https://community.intersystems.com/post/intersystems-data-platforms-and-performance-%E2%80%93-part-1) > 如文章中所述,30 秒收集间隔对于趋势分析和 24 小时报告是合适的。 还有说明用于确保您即使没有运行最新版的 Caché,也能拥有最新版的 pButtons:[InterSystems 数据平台和性能 – 如何更新 pButtons](https://community.intersystems.com/post/intersystems-data-platforms-and-performance-%E2%80%93-how-update-pbuttons)。 虽然 pButtons 主要是一个支持工具,但您可以通过快速绘制所收集的指标来获得宝贵的系统使用情况洞察:[Yape - 另一个 pButtons 提取程序(自动创建图表)](https://community.intersystems.com/post/yape-yet-another-pbuttons-extractor-and-automatically-create-charts) ---- # 总结 本帖仅触及了监控选项的皮毛,例如 Health Monitor 将以默认设置工作,但随着时间的推移,您将希望探索可自定义的选项来满足您的应用程序配置文件。 ## 接下来的方向? 如我们所见,我们将 System Monitor 和 Health Monitor 实用工具配置为将警报发送到作为中央报告位置的 cconsole.log。 我们使用了 Caché Monitor 将这些警报发送到电子邮件。 有一些第三方工具可以抓取日志并消耗非结构化的日志数据,您可能已经在组织中使用这些工具,而且也没有理由不使用它们。 如今,我看到许多客户在 VMware 上进行虚拟化。 如果您使用 vSphere,请考虑使用 Log Insight 来监视控制台日志。 在撰写本帖时(2018 年 3 月),对于您拥有的每个 vCenter Server 6.0 实例,您都有资格获取一个免费的 vRealize Log Insight for vCenter 25 OSI 许可证。 Log insight 是一个读取非结构化数据的工具,用于日志管理和分析 — 例如,您可以将其与 cconsole.log 配合使用 — 如果您对此感兴趣,请联系 VMware 以了解更多信息。 同时,我正计划在将来的帖子中展示如何将 Log Insight 与 cconsole.log 配合使用。 ---- 如果您在收集指标,您仍然需要研究它们,并了解他们的含义,我将继续发帖来展示如何解释所呈现的信息,特别是性能指标。 ---- # 应用程序性能监视 David Loveluck 在社区中有一系列关于应用程序性能监视的帖子,请在社区中搜索 APM,或者[从这里开始](https://community.intersystems.com/post/what-apm)。 ---- ## 附录:Health Monitor 速查表 本速查表展示了我们在第 3 节看到的 Health Monitor 的启动过程,并完成了传感器阈值的编辑。 首先让我们启动 Health Monitor。 %SYS>**d ^%SYSMONMGR** 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? **6** 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option? **1** Enable Health Monitor? No => **yes** Health Monitor is Enabled. Stop and restart System Monitor to run Health Monitor 如我们从消息中所见,导航回到第一个菜单或再次启动 ^%SYSMONMGR 来停止 System Monitor 并再次启动它,以完成这一过程。 %SYS>**d ^%SYSMONMGR** 1) Start/Stop System Monitor 2) Set System Monitor Options etc... 我们将在这里继续,以编辑 CPUPct 阈值为例。 %SYS>**d ^%SYSMONMGR** 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? **6** 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option? **3** 1) Activate/Deactivate Rules 2) Configure Periods 3) Configure Charts 4) Edit Sensor Objects 5) Reset Defaults 6) Exit Option? **4** 先看一下所有传感器; 1) List Sensor Objects 2) Edit Sensor Object 3) Exit Option? **1** Sensor Base Max Max M Warn Warn M -- ---- --- ----- ---- ------ CPUPct 50 80 0 70 0 CPUusage 50 85 0 75 0 CSPActivity 100 0 2 0 1.6 : : : WDWIJTime 60 0 2 0 1.6 WDWriteSize 1024 0 2 0 1.6 1) List Sensor Objects 2) Edit Sensor Object 3) Exit Option? **2** Cannot configure while System Monitor is running. 1) List Sensor Objects 2) Edit Sensor Object 3) Exit 噢,我们需要先返回并禁用 Health Monitor 和 System Monitor。 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option? **1** Disable Health Monitor? No => **yes** Health Monitor is Disabled. Stop and restart System Monitor to halt Health Monitor 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option?**** 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? **1** 1) Start System Monitor 2) Stop System Monitor 3) Exit Option? **2** Stopping System Monitor... System Monitor stopped 好了,Health Monitor 和 System Monitor 已停止。 现在导航回到 Health Monitor 并编辑一个传感器对象。 1) Start System Monitor 2) Stop System Monitor 3) Exit Option?**** 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? **6** 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option? **3** 1) Activate/Deactivate Rules 2) Configure Periods 3) Configure Charts 4) Edit Sensor Objects 5) Reset Defaults 6) Exit Option? **4** 1) List Sensor Objects 2) Edit Sensor Object 3) Exit Option? **2** 输入传感器名称(如果您知道的话),否则输入“?”以显示列表。 传感器? **?** Num Sensor Threshold 1) CPUPct 2) CPUusage : : : 46) WDWIJTime 47) WDWriteSize Sensor? **1** CPUPct Base? 50 =>**** Enter either an Alert Value or a Multiplier Alert Value? 80 => **85** Setting Max Multiplier and Warn Multiplier to 0. Enter a Warn Value Warn Value? 70 => **75** Sensor object CPUPct updated. Base 50 MaxMult 0 AlertValue 85 WarnMult 0 WarnValue 75 1) List Sensor Objects 2) Edit Sensor Object 3) Exit 现在返回并启用 Health Monitor 和启动 System Monitor。 Option?**** 1) Activate/Deactivate Rules 2) Configure Periods 3) Configure Charts 4) Edit Sensor Objects 5) Reset Defaults 6) Exit Option?**** 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option? **1** Enable Health Monitor? No => **yes** Health Monitor is Enabled. Stop and restart System Monitor to run Health Monitor 1) Enable/Disable Health Monitor 2) View Alerts Records 3) Configure Health Monitor Classes 4) Set Health Monitor Options 5) Exit Option?**** 1) Start/Stop System Monitor 2) Set System Monitor Options 3) Configure System Monitor Classes 4) View System Monitor State 5) Manage Application Monitor 6) Manage Health Monitor 7) View System Data 8) Exit Option? **1** 1) Start System Monitor 2) Stop System Monitor 3) Exit Option? **1** Starting System Monitor... System Monitor started 好了,工作已完成! ----
文章
Hao Ma · 一月 15, 2021

IAM实践指南——OAuth 2.0下的API保卫战(第三部分)

在这个由三个部分组成的系列文章中,介绍了如何在OAuth 2.0标准下使用IAM简单地为IRIS中的未经验证的服务添加安全性。 第一部分介绍了一些OAuth 2.0背景知识,以及IRIS和IAM的一些初始定义和配置,以帮助读者理解确保服务安全的整个过程。 第二部分详细讨论和演示了配置IAM所需的步骤——验证传入请求中的访问令牌,并在验证成功时将请求转发到后端。 本系列的最后一部分将讨论和演示IAM生成访问令牌(充当授权服务器)并对其进行验证时所需的配置,以及一些重要的最终考虑事项。 如果您想试用IAM,请联系InterSystems销售代表。 场景2:IAM作为授权服务器和访问令牌验证器 与上个场景不同的是,该场景中将使用一个名为“OAuth 2.0 Authentication”的插件。 如果要在资源所有者密码凭证流中将IAM作为授权服务器使用,客户端应用程序必须对用户名和密码进行身份验证。只有在身份验证成功时,才能发出获取IAM访问令牌的请求。 首先,将其添加到“SampleIRISService”中。正如下面截屏所示,需要填充一些不同的字段来配置此插件。 首先,将“SampleIRISService”的ID粘贴到“service_id”字段中,这样就可以在服务中启用该插件。 在“config.auth_header_name”字段中,需要指定携带授权令牌的头名称。本例中,我保留默认值“authorization”。 “OAuth 2.0 Authentication”插件支持的OAuth 2.0流包括授权码授权(Authorization Code Grant)、客户端凭证(Client Credentials)、隐式授予(Implicit Grant)或资源所有者密码凭证授权(Resource Owner Password Credentials Grant)。我们在本文中使用的是“资源所有者密码凭证”流,故选中“config.enable_password_grant”。 在“config.provision_key”字段中输入要用作配置密钥的字符串。此值用来向IAM请求访问令牌。 本例中,我保留了所有其他字段的默认值。可以在此处查看插件文档中每个字段的完整引用。 下面是插件配置的最终效果: 创建插件后,需要为“ClientApp”客户端创建凭证。 为此,打开左侧菜单上的“Consumers”,然后单击“ClientApp”。接下来,点击“Credentials”标签,然后点击“New OAuth 2.0 Application”按钮。 在下个页面的“name”字段输入名称,以标识应用程序,在“client_id”和“client_secret”字段分别定义客户端ID和客户端密钥,最后在应用程序中输入URL,在“redirect_uri”字段上授权后,用户将被发送到该URL。然后,单击“Create”。 现在,可以发送请求了。 需要发出的第一个请求是获取IAM访问令牌。“OAuth 2.0 Authentication”插件自动创建一个端点,并将“/oauth2/token”路径附加到已经创建的路由上。 注意:必须使用HTTPS协议和IAM的代理端口(默认端口为8443)监听TLS/SSL请求。这是OAuth 2.0规范要求。 因此在本例中,需要向URL发出一个POST请求: https://iamhost:8443/event/oauth2/token 请求主体中应包括以下JSON: { "client_id": "clientid", "client_secret": "clientsecret", "grant_type": "password", "provision_key": "provisionkey", "authenticated_userid": "1" } 如上所示,该JSON包含了在创建“OAuth 2.0 Authentication”插件时定义的值(如“grant_type”和“provision_key”),以及在创建客户端凭证时定义的值(如“client_id”和“client_secret”)。 当提供的用户名和密码成功通过身份验证后,客户端应用程序还应该添加“authenticated_userid”参数值作为已通过身份验证的用户的唯一标志。 该请求及其响应如下: 现在可以请求从上面的响应中获取事件数据(包括“access_token”值),并作为对URL的GET请求中的“bearner token” https://iamhost:8443/event/1 如果访问令牌过期,可以使用收到的刷新令牌和过期的访问令牌一起生成一个新的访问令牌,方法是向用于获取访问令牌的相同端点发出POST请求,但主体略有不同: { "client_id": "clientid", "client_secret": "clientsecret", "grant_type": "refresh_token", "refresh_token": "E50m6Yd9xWy6lybgo3DOvu5ktZTjzkwF" }  该请求及其响应如下: “OAuth 2.0 Authentication”插件的一个有趣很好的特性是能够查看和禁用访问令牌。 若要查看令牌列表,向以下IAM的Admin API终端发送GET请求即可: https://iamhost:8444/{workspace_name}/oauth2_tokens 其中{workspace_name}是IAM工作区的名称。如果启用了RBAC,则需要输入必要的凭证才能调用IAM Admin API。 注意,“credential_id”是在ClientApp客户端内部创建的OAuth应用程序(本例中名为SampleApp)的id,“service_id”是应用此插件的“SampleIRISService”的id。 要想禁用令牌,可以向以下端点发送删除请求 https://iamhost:8444/Sample/oauth2_tokens/{token_id} 其中{token_id}是要禁用的令牌id。 如果尝试使用无效令牌,将包含该无效令牌的GET请求作为Bearer Token 发送到URL,则会收到一条消息,提示令牌无效或已过期: https://iamhost:8443/event/1 最后需要考虑的因素 本文演示了如何将IAM中的OAuth 2.0身份验证添加到IRIS中未经身份验证的服务中。需要牢记的是,IRIS中的服务本身仍是未经身份验证的。因此,如果有人绕过IAM层直接调用IRIS服务端点,则可以在不经过任何身份验证的情况下查看信息。出于该原因,在网络级别设置安全规则以防止不必要的请求绕过IAM层是很重要的。 可以在此处了解更多有关IAM的信息。 如果您想试用IAM,请联系InterSystems销售代表。
文章
Hao Ma · 一月 30, 2021

WebGateway系列(3): 配置IIS连接IRIS

IIS在Windows Server里是默认安装,在Windows7和Windows10里面需要用户到"控制面板>程序"里面找到"Turn Windows features on or off"的设置来启动。 本文假设IIS已经在用户的服务器上启动,并且正常工作。 通常情况下,当IRIS安装在Windows系统时,用户会在同一台机器上使用IIS,很少有单独安装一台IIS服务器给远程IRIS提供Web服务器的,当然这样也绝无问题。 有两个软件包可以安装CSP Gateway。一个是IRIS的安装包。在IRIS的安装过程中, 如果有IIS正在工作, 那么安装程序会自动的安装CSP Gateway。 2018年以前的Ensemble或者Cache'的版本的安装过程中会跳出一个询问框,让用户选择是否"安装CSP网关。。。”。而后来的版本大多不做询问而自动为用户做了选择。 如果需要强制安装或者不安装CSP Gateway,那么需要在安装中选"Customer Component"设置。 另一个软件包是单独的CSP Gateway安装包, 可以在InterSystems的WRC或者工程师处得到。这是一个只有10多兆的很小的安装包,它只安装CSP Gateway, 并不安装IRIS实例,适合在单独的IIS硬件服务器上安装CSP Gateway; 或者, 当一个服务器上已有了IRIS, 但后来想添加IIS服务和CSP Gateway,用这个单独的安装包也很方便。 单独的CSP Gateway的安装会在IIS的工作目录“C:\Inetpub"下添加子目录CSPGateway,或者WebGateway, 然后在IIS的default Website上添加CSP Gateway的配置。整个配置相当简单。下面的步骤是在Windows10上单独安装Web Gateway安装包2020.1连接同一台服务器上的IRIS的的过程。 其中后面配置CSP Gateway访问IRIS应用的部分可以参考Apache上配置CSP Gateway的文档。 ## CSP Gateway安装 1. 使用浏览器访问 http://localhost, 显示IIS的欢迎主页, 确认IIS已工作。 2. 打开WebGateway-20201.1.xxxx-win_x64应用程序开始安装。安装时会提示用户输入连接的IRIS Server的IP地址和端口。默认的Application Name用CSP,IP地址端口使用localhost, 51773。安装过程会重启IIS服务,安装结束后用户不用手工重启。 3. 安装后的检查IIS - 检查Web Gateway安装后的文件。 确认在IIS的安装目录(默认为C:\inetput)下安装了CSPGateway子目录, 其中包含若干dll文件。它们是IIS中用到的CSP Gateway的模块,在不同的CSP Gateway版本中这些Dll文件的数量和名字稍有不同。 - 创建了c:/intersystems/WebGateway的文件夹,早些的版本中并不创建这个目录。 - 打开IIS配置界面, 确认在Default Site下安装了CSP application. 在某些版本的Web Gateway安装后, /csp被安装为Virtual Directory, 关于IIS中application和virtual diectory的区别请自行查询, 无论安装成那种类型, 对csp的使用和配置没有区别。使用HealthConnect 2018以前版本的安装包安装的CSP Gateway生成CSP和ensemble两个Application。 4. 查看CSP Gateway登录页面。 登录http://localhost/csp/bin/Systems/Module.cxw。 在主页上会显示Web Gateway的版本, Web Server Type是"Microseof-IIS"。配置文件和日志文件在c:\Inetpub\CSPGateway目录下。 (如果是打开时出现HTTP错误500.19, 你需要重启IIS) 5. 查看连接的IRIS Server。 从左边菜单栏进入Server Access配置界面。其中csp是默认安装的IRIS连接。2018以前的版本可能用的是LOCAL。不管怎么说,使用"Edit Server"打开,可以看到连接的IRIS的端口和设置。 配置UserName"CSPSystem"和Password "SYS",并保存。 在左边菜单栏,使用"Test Server Connection"测试到“csp"的连接,测试成功会显示IRIS的版本。 Test Server Connection Server connection test was successful: csp (localhost:51773) $ZVersion: IRIS for Windows (x86-64) 2020.2 (Build 199U) Tue Apr 28 2020 17:17:56 EDT 6. 访问IRIS维护主页 (可选) 从链接 http://WebServer/csp/sys/Utilhome.csp 访问IRIS维护主页System Management Portal应该可以成功了,但您会发现有部分网页内容(element)无法加载。这是因为在默认的安装中,只将"csp cls zen cxw"这4种类型的请求发送给CSP Gateway, 而被称为Static file的文件,比如.js, .css, .png等等类型的文件并没有被发送给CSP Gateway. 这是另外的一个安全机制,强制客户人工的配置是否需要从Web服务器访问IRIS维护主页。如果答案是NO, 那么访问IRIS维护页面就只能通过PWS,用IRIS服务器的52773的接口。 如果用户认为从Web服务器访问IRIS维护页面是必要的, 需要修改CSPFileTypes配置,把任意类型的请求发送给IRIS。 7. 访问IRIS上的其他Web Application IRIS上其他的Web Application, 比如”/api", ”/test"等等,通常情况下当Web Application被添加后,配置会自动同步到Web Gateway, 用户不用去Web Gateway的页面配置路由。但IIS上必须填写响应的配置,才能把请求从IIS发送到CSP Gateway. 这样操作: - 添加applications。如下图所示, 在IIS的default site下添加了两个新application, test和api. - 为每个applcation配置"Handler Mappings"。**使用右边动作栏中的”Add Module Mapping",而不是另3种动作。** 还要注意不要勾选"Request Restrictions"的"invoke handler only if request is mapped to"选择框,这样在"Handler Mappings"页面看到的Path Type一栏中显示的是"Unspecified", 否则会显示"File"或者其他内容。 - 测试访问一些应用, 比如 http://172.16.58.200/api/mgmnt/v2/ http://172.16.58.200/test/test.webservice1.cls 一般情况下,到目前为止IIS已经能够正常工作,将需要的请求发送给IRIS。如果出现故障或者需要调整CSP gateway的配置,请参考[WebGateway系列_配置Apache连接IRIS] 请求如何在nginx配置呢 @Hao.Ma 马老师给看看? 目前只有在线文档, 回头我们写一个贴上来
文章
姚 鑫 · 五月 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中创建消息部分时使用的转换表。
文章
姚 鑫 · 七月 16, 2021

第五章 使用文件

# 第五章 使用文件 # 使用文件 `%Library.File`类提供了几个类方法,允许对文件执行各种操作。 ## 复制文件 若要复制文件,请使用`CopyFile()`方法,该方法返回一个布尔值来指示成功或失败。 此方法采用四个参数: 1. from 从—指定源文件的名称。 2. to至—指定目标文件的名称。 3. pDeleteBeforeCopy —指定在执行复制之前是否删除目标文件(如果存在)。默认值为0。 4. return 返回—输出参数。如果为负,则包含操作系统返回的错误代码,以防方法失败 下面的第一个示例将目录`e:\temp`中的文件`old.txt`复制到`new.txt`。第二个示例将相同的文件复制到默认目录中的`new.txt`。 ```java DHC-APP>write ##class(%File).CopyFile("e:\temp\old.txt", "e:\temp\new.txt", 0, .return) 1 DHC-APP>write ##class(%File).CopyFile("e:\temp\old.txt", "new.txt", 0, .return) 1 ``` 最后一个示例失败,Windows错误代码为2,或“找不到文件” ```java DHC-APP>write ##class(%File).CopyFile("foo.txt", "new.txt", 0, .return) 0 DHC-APP>w return -2 ``` ## 删除文件 要删除文件,请使用`delete()`方法,该方法成功时返回1,失败时返回0。这个方法需要两个参数。第一个参数是要删除的文件的名称。第二个参数是输出参数。如果为负,它包含操作系统返回的错误代码,以防方法失败。 在下面的第一个示例中,方法成功了。第二个示例失败,出现Windows错误代码2或“找不到文件”。 ```java DHC-APP>write ##class(%File).Delete("e:\temp\myfile.txt", .return) 1 DHC-APP>write ##class(%File).Delete("e:\temp\myfile.txt", .return) 0 DHC-APP>w return -2 ``` 要在删除文件时匹配通配符,请使用`ComplexDelete()`方法。第一个参数指定要删除的文件的名称。第二个参数是输出参数。如果为负,它包含操作系统返回的错误代码,以防方法失败。 下面的示例删除所有带有。`e:\temp`目录中的out扩展名。 ```java DHC-APP>write ##class(%File).ComplexDelete("e:\temp\*.out", .return) 1 ``` ## 截断文件 要截断文件,请使用`truncate()`方法,该方法成功时返回1,失败时返回0。这个方法需要两个参数。第一个参数是要截断的文件的名称。第二个参数是输出参数。如果为负,它包含操作系统返回的错误代码,以防方法失败。 如果截断现有文件,方法会从文件中删除内容,但不会从文件系统中删除内容。如果截断不存在的文件,方法会创建一个新的空文件。 在下面的第一个示例中,方法成功了。第二个示例失败,Windows错误代码为5,或“访问被拒绝” ```java USER>write ##class(%File).Truncate("e:\temp\myfile.txt", .return) 1 USER>write ##class(%File).Truncate("e:\no access.txt", .return) 0 USER>write return -5 ``` ## 重命名文件 若要重命名文件,请使用`rename()`方法,该方法成功时返回1,失败时返回0。这个方法需要三个参数。第一个参数是要重命名的文件的名称,第二个参数是新名称。第三个参数是输出参数。如果为负,它包含操作系统返回的错误代码,以防方法失败。 在下面的第一个示例中,方法成功了。第二个示例失败,错误代码为183,或者“当文件已经存在时,无法创建该文件。” ```java DHC-APP>write ##class(%File).Rename("e:\temp\oldname.txt", "e:\temp\newname.txt", .return) 1 DHC-APP>write ##class(%File).Rename("e:\temp\another.txt", "e:\temp\newname.txt", .return) 0 DHC-APP>write return -2 ``` 使用此方法时,请小心指定路径,因为以下示例会将`e:\temp\oldname.txt`移动到默认目录,然后将其重命名为`newname.txt`。 ```java DHC-APP>write ##class(%File).Rename("e:\temp\oldname.txt", "newname.txt", .return) 1 ``` ## 比较文件 若要比较两个文件,请使用`Compare()`方法,如果两个文件相同,则返回布尔值1,否则返回0。该方法没有用于返回系统错误代码的输出参数。 在下面的第一个示例中,两个文件是相同的,方法返回1。在第二个示例中,两个文件不同,因此方法返回0。 ```java DHC-APP>write ##class(%File).Compare("e:\temp\old.txt", "e:\temp\new.txt") 1 DHC-APP>write ##class(%File).Compare("e:\temp\old.txt", "e:\temp\another.txt") 0 ``` 如果一个或两个文件都不存在,如下例所示,则该方法也返回0。 ```java DHC-APP>write ##class(%File).Compare("foo.txt", "bar.txt") 0 DHC-APP>write ##class(%File).Exists("foo.txt") 0 ``` ## 生成临时文件 要生成临时文件,请使用`TempFilename()`方法,该方法返回临时文件的名称。这个方法需要三个参数。第一个参数是临时文件所需的文件扩展名。第二个是生成临时文件的目录。如果未提供,该方法将在操作系统提供的临时目录中生成文件。第三个参数是输出参数。如果为负,它包含操作系统返回的错误代码,以防方法失败。 Windows示例: ```java USER>write ##class(%File).TempFilename("txt") C:\WINDOWS\TEMP\GATqk8a6.txt USER>write ##class(%File).TempFilename("txt","C:\temp") C:\temp\WpSwuLlA.txt ``` Unix示例: ```java USER>write ##class(%File).TempFilename("", "", .return) /tmp/filsfHGzc USER>write ##class(%File).TempFilename("tmp", "/InterSystems/temp", .return) /InterSystems/temp/file0tnuh.tmp USER>write ##class(%File).TempFilename("", "/tmp1", .return) USER>write return -2 ``` 在上面的第三个示例中,目录不存在,该方法失败,系统错误代码为2,或“没有这样的文件或目录。”
文章
Qiao Peng · 十月 22, 2022

SQL业务服务和业务操作

1. 新的系统SQL业务服务/业务操作 接连SQL数据源和操作SQL数据目标是常见的集成业务场景。使用SQL适配器监控SQL数据源和操作SQL目标库时,我们需要开发自定义BS或BO,写不少代码。例如开发自定义SQL服务需要: 1. 开发响应消息类,用于承接SQL快照数据; 2. 开发自定义业务服务BS类,用于将SQL快照按字段赋值给对应的消息,并将消息发送给目标(业务流程或业务操作)。 而要开发自定义SQL操作,更麻烦些: 1. 开发请求和响应消息类,用于向BO传输数据和接收返回数据; 2. 开发自定义业务服务BO类,设置消息响应表,根据不同请求消息类型编写方法; 3. 在方法中根据请求消息数据拼写SQL语句; 4. 在方法中将SQL执行结果存入响应消息。 虽然很简单,但编程过程枯燥乏味。而且当修改SQL语句时,还要修改对应的消息类和BS/BO类。 从2021.2开始,InterSystems IRIS增加了2套系统SQL业务服务和SQL业务操作: BS EnsLib.SQL.Service.GenericService 使用SQL语句 BS EnsLib.SQL.Service.ProcService 使用存储过程 BO EnsLib.SQL.Operation.GenericOperation 使用SQL语句 BO EnsLib.SQL.Operation.ProcOperation 使用存储过程 只要直接将它们加入Production,就可以直接使用了,甚至无需再定义消息,真正实现无代码开发,nice! 2. 如何使用系统SQL业务服务/业务操作 下面我们来看看它们是怎么实现的,以及如何使用它们。 2.1 SQL业务服务 直接将EnsLib.SQL.Service.GenericService或EnsLib.SQL.Service.ProcService加入Production的BS中,并设置数据源、SQL语句和发送目标: 一步搞定,且无需使用IDE开发任何一行代码! 那么SQL业务操作发送给目标业务组件的是什么消息呢? 默认是Ens.StreamContainer,而结果集数据是以JSON表达并放在其Stream属性(流类型)下的,正好用到JSON免schema的特性。类似于: 如果你已经有一个消息类,想让SQL业务服务将结果集记录放在这个消息里?只要设置SQL业务服务的“消息类”即可: 当然,你自己定义的消息属性名要和返回的SQL结果集字段名一致,否则会报错。如果消息是以前定义好的,那么通过SQL语句使用AS来修改字段名最简单,例如SELECT NAME AS Display... 对如何操作JSON不熟? 在InterSystems IRIS/Cache'里,系统类%DynamicObject就是JSON对象,它有方法%FromJSON可以直接将JSON字符串/字符流转为JSON对象。所以可以直接以对象的方式操作JSON,就像下面在业务流程里将Ens.StreamContainer的Stream属性转为JSON对象使用: 2.2 SQL 业务操作 同样,SQL业务操作也无需代码开发。直接将EnsLib.SQL.Operation.GenericOperation或EnsLib.SQL.Operation.ProcOperation加入Production,进行配置即可。 配置项除了SQL数据目标的连接信息外,就是要执行的SQL语句了: 在 查询 中添加SQL语句,如果SQL语句中有任何参数需要传入,用"?" 代表。例如 Insert into QP.Patient(Gender,Name) values(?,?) 如果SQL需要输入参数,在 输入参数 中按顺序添加需要的参数,一般情况下是使用请求消息里的属性,在需要用的属性名前面加 *,说明这个参数来自请求消息。例如*Sex,*Name。 好,配置完成,依然没写一行代码! 但慢着,我们没有对这个BO定义请求消息呀? 我们不需要事先声明任何请求消息类,EnsLib.SQL.Operation.GenericOperation和EnsLib.SQL.Operation.ProcOperation可以接受任何类型的请求消息! 那么像上面的例子中提到的传入参数*Sex,*Name,是不是我必须要事先建一个请求消息类,里面有Sex和Name属性? 完全不必要!你可以直接通过系统请求消息Ens.StreamContainer、Ens.StringContainer、Ens.StringRequest传入JSON字符串/字符流即可,SQL业务操作会自动将JSON实例化为JSON对象。因此上面例子,可以传入Ens.StringRequest,只要JSON字符串里有Sex和Name这2个数据即可。 例如你可以直接测试这个BO: 是不是非常方便! * 注意:当使用Ens.StreamContainer、Ens.StringContainer、Ens.StringRequest 这些请求消息时,数据一定要是JSON格式的字符串/字符流,否则会得到报错信息! 那么SQL执行返回的结果在哪里? BO默认的响应消息是StreamContainer,因此执行结果都以JSON格式在它里面。 如果执行的SQL是INSERT/UPDATE/DELETE,那么返回的只有SQL语句影响的行数,放在NumRowsAffected里,如下: 如果执行的SQL是SELECT,则返回的是结果集如下: 如果你已经有定义过的消息类用于接收返回的SQL结果集,可以设置其“响应类”属性: SQL业务操作会将返回结果集的第一行按字段名对应保存到响应消息的属性上。 *注意:当SQL返回的结果集有多行记录时,这种使用用户自定义响应消息的情况下,会在事件日志中记录一条信息,并只将结果集第一行对应到自定义响应消息中! 今后连接SQL数据源和数据目标时,使用这2套系统SQL业务服务和业务操作,可以快乐地玩耍了!
文章
Michael Lei · 七月 3, 2023

基于LangChain的IRIS ChatGPT – 释放大语言模型LLM的全部潜力

你好社区在本文中,我将介绍我的应用程序irisChatGPT ,它是基于LangChain Framework构建的。首先,让我们对框架进行一个简单的概述。 全世界都在谈论ChatGPT以及大型语言模型 (LLM) 如何变得如此强大,并且表现超出预期,提供类似人类的对话。这只是将其应用于每个企业和每个领域的开始! 剩下的最重要的问题是如何将这种能力应用于适合企业需求的特定领域数据和特定场景响应行为。 LangChain为这个问题提供了结构化且有效的答案! LangChain 技术可以帮助实现法学硕士的巨大潜力,通过围绕法学硕士提供抽象层并使法学硕士的使用变得简单有效,从而构建令人惊叹的应用程序。 LangChain 是一个框架,可以快速轻松地开发使用大型语言模型(例如 GPT-3)的应用程序。 然而,该框架引入了额外的可能性,例如,轻松使用外部数据源(例如维基百科)来放大模型提供的功能。我相信你们都可能尝试过使用 Chat-GPT,并发现它无法回答特定日期之后发生的事件。在这种情况下,在维基百科上搜索可以帮助 GPT 回答更多问题。 LangChain结构 该框架分为六个模块,每个模块允许您管理与法学硕士互动的不同方面。让我们看看这些模块是什么。 模型:允许您实例化和使用三种不同类型的语言模型,它们是: 大型语言模型 (LLM):这些能够理解自然语言的基础机器学习模型。它们接受输入中的字符串并在输出中生成字符串。 聊天模型:由 LLM 支持的模型,但专门用于与用户聊天。您可以在这里阅读更多内容。 文本嵌入模型:这些模型用于将文本数据投影到几何空间中。这些模型将文本作为输入并返回数字列表,即文本的嵌入。 提示:提示是我们如何与模型交互以尝试从中获取输出。现在知道如何编写有效的提示至关重要。这个框架模块可以让我们更好的管理提示。例如,通过创建我们可以重用的模板。 索引:最好的模型通常是与一些文本数据相结合的模型,以便为模型添加上下文或解释某些内容。这个模块可以帮助我们做到这一点。 链:很多时候,要解决任务,对 LLM 的单个 API 调用是不够的。该模块允许集成其他工具。例如,一个调用可以是一个组合链,其目的是从维基百科获取信息,然后将此信息作为模型的输入。该模块允许连接多个工具以解决复杂的任务。 内存:该模块允许我们在模型调用之间创建持久状态。能够使用记住过去说过的话的模型肯定会改善我们的应用程序。 代理:代理是一个法学硕士,它做出决定,采取行动,观察其所做的事情,并以这种方式继续,直到完成其任务。该模块提供了一组可以使用的代理。 现在让我们更详细地了解一下如何利用不同的模块来实现代码。 Langchain工作原理 步骤1 :用户向LangChain发送问题第2步 :LangChain将此问题发送至Embedding Model步骤3:嵌入模型将文本转换为向量,文本以向量形式存储在数据库中并返回给LangChain步骤4 :LangChain将这些向量发送到向量数据库(有多个向量数据库,我们在我们的应用程序中使用chroma)步骤5:向量数据库返回前 K 个近似最近邻 ( KNN ) 向量第6步:LangChain 将问题与KNN向量一起发送到大型语言模型 (LLM) (我们在应用程序中使用 OpenAI)步骤7:LLM向Langchain返回答案步骤8:Langchain将答案返回给用户 关于申请 irisChatGPT应用程序利用围绕大型语言模型 (LLM) 构建的最热门 Python 框架LangChain的功能。 LangChain 是一个框架,可以快速轻松地开发使用大型语言模型的应用程序。应用程序是在系统间嵌入式 Python功能的帮助下使用 objectscript 构建的。它还包含Streamlit Web 应用程序,这是一个开源 Python 应用程序框架,用于为数据科学和机器学习创建漂亮的 Web 应用程序。 特征 以下是应用程序功能列表以及相关屏幕截图 内置Intersystems ObjectScript 参考ChatGPT 内置InterSystems 大奖赛 2023 ChatGPT 使用 SQLDatabaseChain 回答有关缓存数据库的问题 创建您自己的 chatGPT 模型并与其聊天 OpenAI 聊天GPT 维基百科搜索 使用DuckDuckGo(DDG)通用搜索引擎在互联网上搜索 使用Python REPL LangChain功能生成Python代码 Streamlit Web 应用程序在线演示 谢谢
文章
jieliang liu · 二月 5, 2021

精华文章置顶--使用VSCode 进行IRIS 开发

VSCode 是目前很流行的一款免费开发工具,IRIS也支持使用其进行连接和开发,相比Studio 只能在windows 环境使用,Vscode 可以跨平台使用。 我们传统的工具Studio 是连接代码服务器的形式,不能便捷的使用目前流行的有本地代码的版本控制工具(如git),但VSCode可以存在本地代码,并且能方便的使用各类存在本地代码的版本控制工具。 以下的内容会帮助大家来配置使用VSCode连接IRIS 进行开发。 VSCode 可以在微软的官网免费下载https://code.visualstudio.com/ 如果安装为英文要切换为中文则可以通过Command Palette 中运行Configure Display Language,install another language, 选择中文,再根据提示安装相应的语言插件。 接下来在扩展商店里搜索intersystems 安装如图所见的3个扩展包 VSCode目前有两种方式可以链接IRIS: 直接连接代码服务器进行编辑 使用客户端方式连接,将代码下载到本地,便于使用有本地代码的版本控制工具 注:两种连接方式的连接端口都为服务器web port 下面具体讲解两种连接方式。 直接连接代码服务器进行编辑 其总体的使用方式和studio相似,直接连接服务器进行代码编辑。在vscode中可以使用全局只读的方式来浏览代码,从而避免误操作修改了代码。 如果会经常使用这个服务器,可以考虑先建立一个工作区,将设置保存在工作区,当然直连服务器的模式下,建立服务器不是必选项。 如果我们正确的安装了之前提到的三个扩展,其中下面扩展会帮助我们连接IRIS代码服务器,并保存在VSCode的全局 settings.json配置文件中: 进入VSCode 设置中找到“扩展”下的Intersystems Server Manager ,进入设置可见安装自带的服务器连接字符串可以依据用户需要进行添加和修改 配置完成可以回到工作区界面进行连接 选择Choose Server and Namespaces, 从右边的服务器列表中选择要连接的服务器,也可以使用“+”来根据提示信息来添加新的服务器。 选择服务器之后会提示输入密码(如果没有在配置中写明登录用户,也会提示输入登录用户)验证成功后可以选择想查看的命名空间,最后按照提示选择是以编辑或者只读方式来查看代码。 在服务器直连的模式下,可以将多个服务器的多个命名空间的代码添加至当前工作区。 目前的连接方式进入之后会频繁的要求登录验证,输入密码,这里实际可以将密码存在VSCode的钥匙链中: 1.打开命令面板 2.输入store 使用下图中的命令则可以为选定的服务器存储密码,但是每个服务器只能保存一个密码,相应的在命令面板中输入clear 会提示清除密码的选项用来删除已存储的密码 2. 使用客户端方式连接 如果使用客户端的连接方式,则必须要在工作区内添加一个文件夹,以及保存此工作区。当添加文件夹到工作区之后侧边栏会多出图示的按钮: 点击按钮选择Choose server and namespaces 此时如果在vscode中已经添加过想要连接的IRIS 代码服务器,这里会直接显示已存储的服务器,设置法与之前提到的直连方式相同。 连接完成后如果想添加多个命名空间到工作区,可以使用右上角的+号进行添加 接下来可以在客户端模式连接导出ObjectScript代码到本地。从而进行源代码的版本控制管理。 在objectscript explorer中选择任意的包,或者类右键选择export,则可以将其导出到目前工作区的文件夹下 代码会被导出到工作区目录的src文件夹下。 客户端模式中使用 GIT 首先打开一个GIT Repo文件夹,如果本来然后按照客户端连接方式连接用来开发的服务器。在任何的包或文件上点击import and compile 可以将版本控制的代码导入开发服务器。 注意这时候只要在本地新建文件并且保存,新的修改就会被同步到开发服务器实例上。 以客户端方式连接时连接多个服务器或多个命名空间的方式: 首先将一个文件夹添加到工作区,并保存工作区,在保存之后的工作区中可以看到如下的工作区配置文件( 此处我使用的默认工作区配置文件名,实际可以自行定义),其中定义了工作区的目录结构: 此时我们在这个工作区内添加一个子目录,在工作区的列表右键单击,选择“将文件夹添加到工作区”: 添加后可以看到,在工作区配置文件中增加了新的目录,为了这个显示层级更加清楚,可以在settings 中使用files.exclude 来过滤是否显示子目录 此时子再点击侧边栏中的 object script explorer,则会让用户选择使用哪一个子目录进行连接: 要使用另一个目录连接一个服务器的命名空间时,将第一个已连接的文件夹下.vscode 拷贝到第二个文件夹: 直接对这个文件进行修改,将其配置成为想连接的服务器以及命名空间 连接配置文件同样支持如下的写法: 此时再回到object script exploer,可见到添加了的服务器。 可见这里服务器的连接和本地代码编译的目标对象只由当前文件夹下.vscode/settings.json控制。 所有的之前提到的配置文件都可以手工编辑,不必一定在vscode中进行添加文件夹和配置连接。 在VSCode中调试 以客户端方式连接时可以进行调试: 在侧边栏选择调试按钮,首次调试应在工作区创建launch.json,并选择ObjectScript Debug 对于Class Method,可以直接在类中点击“Debug this Method” 下边是一个Class Method 实例的实例调试界面 附加到进程调试: 对于需要附加到的进程,在lauch.json中添加”program” 属性,并填入进程号,保存。 program 中也可以填入要debug的routine 比如“##class(Test.test).test()”, “name”可以修改成自定义的名字,之后会在debug运行按钮的下拉菜单显示。 调试的配置可以添加多个,都会显示在debug下拉菜单中 进入调试界面,点击xDebug 旁边的绿色启动按钮开始调试,其他同Class Method 调试方式 关于VSCode几个编辑器小技巧: 在底部栏点击当前连接的服务器会出现提示菜单,从这里可以便捷进入实例管理界面和class reference 在任意的类或者方法上点击右键可以转到定义。如果使用了#dim预定义变量,则可以在变量上使用转到变量声明,而且可以使用转到类型定义类型的定义。 尾声 当前版本不支持xml 代码文件导入!VSCode community中已经有人提到过这个问题,开发者回复之后的版本很有可能会加入 本项目的Github的issue地址,可以在这里提出问题:https://github.com/intersystems-community/vscode-objectscript/issues 支持的产品 :Caché/Ensemble 2016.2 以及更新, 以及所有的基于IRIS 的产品版本. 调试入参类型为%Library.DynamicAbstractObjec的参数如何输入入参呢 对象入参的话,的确直接调试没法从键盘输入,可能还是需要附加到进程或者写一个临时方法来生成这个入参对象,再调用想调试的方法检查断点。 知乎文章:使用VS Code进行Caché数据库开发 好的,谢谢