搜索​​​​

清除过滤器
文章
jieliang liu · 九月 23, 2021

IRIS 2021 技术文档 First Look 19 使用 InterSystems 产品优化 SQL 性能

html {overflow-x: initial !important;}:root { --bg-color: #ffffff; --text-color: #333333; --select-text-bg-color: #B5D6FC; --select-text-font-color: auto; --monospace: "Lucida Console",Consolas,"Courier",monospace; --title-bar-height: 20px; } .mac-os-11 { --title-bar-height: 28px; } html { font-size: 14px; background-color: var(--bg-color); color: var(--text-color); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; } body { margin: 0px; padding: 0px; height: auto; inset: 0px; font-size: 1rem; line-height: 1.42857143; overflow-x: hidden; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; tab-size: 4; background-position: inherit; background-repeat: inherit; } iframe { margin: auto; } a.url { word-break: break-all; } a:active, a:hover { outline: 0px; } .in-text-selection, ::selection { text-shadow: none; background: var(--select-text-bg-color); color: var(--select-text-font-color); } #write { margin: 0px auto; height: auto; width: inherit; word-break: normal; word-wrap: break-word; position: relative; white-space: normal; overflow-x: visible; padding-top: 36px; } #write.first-line-indent p { text-indent: 2em; } #write.first-line-indent li p, #write.first-line-indent p * { text-indent: 0px; } #write.first-line-indent li { margin-left: 2em; } .for-image #write { padding-left: 8px; padding-right: 8px; } body.typora-export { padding-left: 30px; padding-right: 30px; } .typora-export .footnote-line, .typora-export li, .typora-export p { white-space: pre-wrap; } .typora-export .task-list-item input { pointer-events: none; } @media screen and (max-width: 500px) { body.typora-export { padding-left: 0px; padding-right: 0px; } #write { padding-left: 20px; padding-right: 20px; } .CodeMirror-sizer { margin-left: 0px !important; } .CodeMirror-gutters { display: none !important; } } #write li > figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max-width: 100%; vertical-align: middle; image-orientation: from-image; } button, input, select, textarea { color: inherit; font-family: inherit; font-size: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; } input[type="checkbox"], input[type="radio"] { line-height: normal; padding: 0px; } *, ::after, ::before { box-sizing: border-box; } #write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write p, #write pre { width: inherit; } #write h1, #write h2, #write h3, #write h4, #write h5, #write h6, #write p { position: relative; } p { line-height: inherit; } h1, h2, h3, h4, h5, h6 { break-after: avoid-page; break-inside: avoid; orphans: 4; } p { orphans: 4; } h1 { font-size: 2rem; } h2 { font-size: 1.8rem; } h3 { font-size: 1.6rem; } h4 { font-size: 1.4rem; } h5 { font-size: 1.2rem; } h6 { font-size: 1rem; } .md-math-block, .md-rawblock, h1, h2, h3, h4, h5, h6, p { margin-top: 1rem; margin-bottom: 1rem; } .hidden { display: none; } .md-blockmeta { color: rgb(204, 204, 204); font-weight: 700; font-style: italic; } a { cursor: pointer; } sup.md-footnote { padding: 2px 4px; background-color: rgba(238, 238, 238, 0.7); color: rgb(85, 85, 85); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; cursor: pointer; } sup.md-footnote a, sup.md-footnote a:hover { color: inherit; text-transform: inherit; text-decoration: inherit; } #write input[type="checkbox"] { cursor: pointer; width: inherit; height: inherit; } figure { overflow-x: auto; margin: 1.2em 0px; max-width: calc(100% + 16px); padding: 0px; } figure > table { margin: 0px; } tr { break-inside: avoid; break-after: auto; } thead { display: table-header-group; } table { border-collapse: collapse; border-spacing: 0px; width: 100%; overflow: auto; break-inside: auto; text-align: left; } table.md-table td { min-width: 32px; } .CodeMirror-gutters { border-right-width: 0px; background-color: inherit; } .CodeMirror-linenumber { } .CodeMirror { text-align: left; } .CodeMirror-placeholder { opacity: 0.3; } .CodeMirror pre { padding: 0px 4px; } .CodeMirror-lines { padding: 0px; } div.hr:focus { cursor: none; } #write pre { white-space: pre-wrap; } #write.fences-no-line-wrapping pre { white-space: pre; } #write pre.ty-contain-cm { white-space: normal; } .CodeMirror-gutters { margin-right: 4px; } .md-fences { font-size: 0.9rem; display: block; break-inside: avoid; text-align: left; overflow: visible; white-space: pre; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; position: relative !important; background-position: inherit; background-repeat: inherit; } .md-fences-adv-panel { width: 100%; margin-top: 10px; text-align: center; padding-top: 0px; padding-bottom: 8px; overflow-x: auto; } #write .md-fences.mock-cm { white-space: pre-wrap; } .md-fences.md-fences-with-lineno { padding-left: 0px; } #write.fences-no-line-wrapping .md-fences.mock-cm { white-space: pre; overflow-x: auto; } .md-fences.mock-cm.md-fences-with-lineno { padding-left: 8px; } .CodeMirror-line, twitterwidget { break-inside: avoid; } .footnotes { opacity: 0.8; font-size: 0.9rem; margin-top: 1em; margin-bottom: 1em; } .footnotes + .footnotes { margin-top: 0px; } .md-reset { margin: 0px; padding: 0px; border: 0px; outline: 0px; vertical-align: top; text-decoration: none; text-shadow: none; float: none; position: static; width: auto; height: auto; white-space: nowrap; cursor: inherit; line-height: normal; font-weight: 400; text-align: left; box-sizing: content-box; direction: ltr; background-position: 0px 0px; } li div { padding-top: 0px; } blockquote { margin: 1rem 0px; } li .mathjax-block, li p { margin: 0.5rem 0px; } li blockquote { margin: 1rem 0px; } li { margin: 0px; position: relative; } blockquote > :last-child { margin-bottom: 0px; } blockquote > :first-child, li > :first-child { margin-top: 0px; } .footnotes-area { color: rgb(136, 136, 136); margin-top: 0.714rem; padding-bottom: 0.143rem; white-space: normal; } #write .footnote-line { white-space: pre-wrap; } @media print { body, html { border: 1px solid transparent; height: 99%; break-after: avoid; break-before: avoid; font-variant-ligatures: no-common-ligatures; } #write { margin-top: 0px; padding-top: 0px; border-color: transparent !important; } .typora-export * { -webkit-print-color-adjust: exact; } .typora-export #write { break-after: avoid; } .typora-export #write::after { height: 0px; } .is-mac table { break-inside: avoid; } .typora-export-show-outline .typora-export-sidebar { display: none; } } .footnote-line { margin-top: 0.714em; font-size: 0.7em; } a img, img a { cursor: pointer; } pre.md-meta-block { font-size: 0.8rem; min-height: 0.8rem; white-space: pre-wrap; background-color: rgb(204, 204, 204); display: block; overflow-x: hidden; } p > .md-image:only-child:not(.md-img-error) img, p > img:only-child { display: block; margin: auto; } #write.first-line-indent p > .md-image:only-child:not(.md-img-error) img { left: -2em; position: relative; } p > .md-image:only-child { display: inline-block; width: 100%; } #write .MathJax_Display { margin: 0.8em 0px 0px; } .md-math-block { width: 100%; } .md-math-block:not(:empty)::after { display: none; } .MathJax_ref { fill: currentcolor; } [contenteditable="true"]:active, [contenteditable="true"]:focus, [contenteditable="false"]:active, [contenteditable="false"]:focus { outline: 0px; box-shadow: none; } .md-task-list-item { position: relative; list-style-type: none; } .task-list-item.md-task-list-item { padding-left: 0px; } .md-task-list-item > input { position: absolute; top: 0px; left: 0px; margin-left: -1.2em; margin-top: calc(1em - 10px); border: none; } .math { font-size: 1rem; } .md-toc { min-height: 3.58rem; position: relative; font-size: 0.9rem; border-top-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; } .md-toc-content { position: relative; margin-left: 0px; } .md-toc-content::after, .md-toc::after { display: none; } .md-toc-item { display: block; color: rgb(65, 131, 196); } .md-toc-item a { text-decoration: none; } .md-toc-inner:hover { text-decoration: underline; } .md-toc-inner { display: inline-block; cursor: pointer; } .md-toc-h1 .md-toc-inner { margin-left: 0px; font-weight: 700; } .md-toc-h2 .md-toc-inner { margin-left: 2em; } .md-toc-h3 .md-toc-inner { margin-left: 4em; } .md-toc-h4 .md-toc-inner { margin-left: 6em; } .md-toc-h5 .md-toc-inner { margin-left: 8em; } .md-toc-h6 .md-toc-inner { margin-left: 10em; } @media screen and (max-width: 48em) { .md-toc-h3 .md-toc-inner { margin-left: 3.5em; } .md-toc-h4 .md-toc-inner { margin-left: 5em; } .md-toc-h5 .md-toc-inner { margin-left: 6.5em; } .md-toc-h6 .md-toc-inner { margin-left: 8em; } } a.md-toc-inner { font-size: inherit; font-style: inherit; font-weight: inherit; line-height: inherit; } .footnote-line a:not(.reversefootnote) { color: inherit; } .md-attr { display: none; } .md-fn-count::after { content: "."; } code, pre, samp, tt { font-family: var(--monospace); } kbd { margin: 0px 0.1em; padding: 0.1em 0.6em; font-size: 0.8em; color: rgb(36, 39, 41); background-color: rgb(255, 255, 255); border: 1px solid rgb(173, 179, 185); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; box-shadow: rgba(12, 13, 14, 0.2) 0px 1px 0px, rgb(255, 255, 255) 0px 0px 0px 2px inset; white-space: nowrap; vertical-align: middle; } .md-comment { color: rgb(162, 127, 3); opacity: 0.8; font-family: var(--monospace); } code { text-align: left; } a.md-print-anchor { white-space: pre !important; border: none !important; display: inline-block !important; position: absolute !important; width: 1px !important; right: 0px !important; outline: 0px !important; text-shadow: initial !important; background-position: 0px 0px !important; } .os-windows.monocolor-emoji .md-emoji { font-family: "Segoe UI Symbol", sans-serif; } .md-diagram-panel > svg { max-width: 100%; } [lang="flow"] svg, [lang="mermaid"] svg { max-width: 100%; height: auto; } [lang="mermaid"] .node text { font-size: 1rem; } table tr th { border-bottom-width: 0px; } video { max-width: 100%; display: block; margin: 0px auto; } iframe { max-width: 100%; width: 100%; border: none; } .highlight td, .highlight tr { border: 0px; } mark { background-color: rgb(255, 255, 0); color: rgb(0, 0, 0); } .md-html-inline .md-plain, .md-html-inline strong, mark .md-inline-math, mark strong { color: inherit; } .md-expand mark .md-meta { opacity: 0.3 !important; } mark .md-meta { color: rgb(0, 0, 0); } @media print { .typora-export h1, .typora-export h2, .typora-export h3, .typora-export h4, .typora-export h5, .typora-export h6 { break-inside: avoid; } } .md-diagram-panel .messageText { stroke: none !important; } .md-diagram-panel .start-state { fill: var(--node-fill); } .md-diagram-panel .edgeLabel rect { opacity: 1 !important; } .md-require-zoom-fix { height: auto; margin-top: 16px; margin-bottom: 16px; } .md-require-zoom-fix foreignObject { font-size: var(--mermaid-font-zoom); } .md-fences.md-fences-math { font-size: 1em; } .md-fences-advanced:not(.md-focus) { padding: 0px; white-space: nowrap; border: 0px; } .md-fences-advanced:not(.md-focus) { background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; background-position: inherit; background-repeat: inherit; } .typora-export-show-outline .typora-export-content { max-width: 1440px; margin: auto; display: flex; flex-direction: row; } .typora-export-sidebar { width: 300px; font-size: 0.8rem; margin-top: 80px; margin-right: 18px; } .typora-export-show-outline #write { --webkit-flex: 2; flex: 2 1 0%; } .typora-export-sidebar .outline-content { position: fixed; top: 0px; max-height: 100%; overflow: hidden auto; padding-bottom: 30px; padding-top: 60px; width: 300px; } @media screen and (max-width: 1024px) { .typora-export-sidebar, .typora-export-sidebar .outline-content { width: 240px; } } @media screen and (max-width: 800px) { .typora-export-sidebar { display: none; } } .outline-content li, .outline-content ul { margin-left: 0px; margin-right: 0px; padding-left: 0px; padding-right: 0px; list-style: none; } .outline-content ul { margin-top: 0px; margin-bottom: 0px; } .outline-content strong { font-weight: 400; } .outline-expander { width: 1rem; height: 1.428571429rem; position: relative; display: table-cell; vertical-align: middle; cursor: pointer; padding-left: 4px; } .outline-expander::before { content: ''; position: relative; font-family: Ionicons; display: inline-block; font-size: 8px; vertical-align: middle; } .outline-item { padding-top: 3px; padding-bottom: 3px; cursor: pointer; } .outline-expander:hover::before { content: ''; } .outline-h1 > .outline-item { padding-left: 0px; } .outline-h2 > .outline-item { padding-left: 1em; } .outline-h3 > .outline-item { padding-left: 2em; } .outline-h4 > .outline-item { padding-left: 3em; } .outline-h5 > .outline-item { padding-left: 4em; } .outline-h6 > .outline-item { padding-left: 5em; } .outline-label { cursor: pointer; display: table-cell; vertical-align: middle; text-decoration: none; color: inherit; } .outline-label:hover { text-decoration: underline; } .outline-item:hover { border-color: rgb(245, 245, 245); background-color: var(--item-hover-bg-color); } .outline-item:hover { margin-left: -28px; margin-right: -28px; border-left-width: 28px; border-left-style: solid; border-left-color: transparent; border-right-width: 28px; border-right-style: solid; border-right-color: transparent; } .outline-item-single .outline-expander::before, .outline-item-single .outline-expander:hover::before { display: none; } .outline-item-open > .outline-item > .outline-expander::before { content: ''; } .outline-children { display: none; } .info-panel-tab-wrapper { display: none; } .outline-item-open > .outline-children { display: block; } .typora-export .outline-item { padding-top: 1px; padding-bottom: 1px; } .typora-export .outline-item:hover { margin-right: -8px; border-right-width: 8px; border-right-style: solid; border-right-color: transparent; } .typora-export .outline-expander::before { content: "+"; font-family: inherit; top: -1px; } .typora-export .outline-expander:hover::before, .typora-export .outline-item-open > .outline-item > .outline-expander::before { content: '−'; } .typora-export-collapse-outline .outline-children { display: none; } .typora-export-collapse-outline .outline-item-open > .outline-children, .typora-export-no-collapse-outline .outline-children { display: block; } .typora-export-no-collapse-outline .outline-expander::before { content: "" !important; } .typora-export-show-outline .outline-item-active > .outline-item .outline-label { font-weight: 700; } .md-inline-math-container mjx-container { zoom: 0.95; } .CodeMirror { height: auto; } .CodeMirror.cm-s-inner { background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; background-position: inherit; background-repeat: inherit; } .CodeMirror-scroll { overflow: auto hidden; z-index: 3; } .CodeMirror-gutter-filler, .CodeMirror-scrollbar-filler { background-color: rgb(255, 255, 255); } .CodeMirror-gutters { border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; white-space: nowrap; background-position: inherit; background-repeat: inherit; } .CodeMirror-linenumber { padding: 0px 3px 0px 5px; text-align: right; color: rgb(153, 153, 153); } .cm-s-inner .cm-keyword { color: rgb(119, 0, 136); } .cm-s-inner .cm-atom, .cm-s-inner.cm-atom { color: rgb(34, 17, 153); } .cm-s-inner .cm-number { color: rgb(17, 102, 68); } .cm-s-inner .cm-def { color: rgb(0, 0, 255); } .cm-s-inner .cm-variable { color: rgb(0, 0, 0); } .cm-s-inner .cm-variable-2 { color: rgb(0, 85, 170); } .cm-s-inner .cm-variable-3 { color: rgb(0, 136, 85); } .cm-s-inner .cm-string { color: rgb(170, 17, 17); } .cm-s-inner .cm-property { color: rgb(0, 0, 0); } .cm-s-inner .cm-operator { color: rgb(152, 26, 26); } .cm-s-inner .cm-comment, .cm-s-inner.cm-comment { color: rgb(170, 85, 0); } .cm-s-inner .cm-string-2 { color: rgb(255, 85, 0); } .cm-s-inner .cm-meta { color: rgb(85, 85, 85); } .cm-s-inner .cm-qualifier { color: rgb(85, 85, 85); } .cm-s-inner .cm-builtin { color: rgb(51, 0, 170); } .cm-s-inner .cm-bracket { color: rgb(153, 153, 119); } .cm-s-inner .cm-tag { color: rgb(17, 119, 0); } .cm-s-inner .cm-attribute { color: rgb(0, 0, 204); } .cm-s-inner .cm-header, .cm-s-inner.cm-header { color: rgb(0, 0, 255); } .cm-s-inner .cm-quote, .cm-s-inner.cm-quote { color: rgb(0, 153, 0); } .cm-s-inner .cm-hr, .cm-s-inner.cm-hr { color: rgb(153, 153, 153); } .cm-s-inner .cm-link, .cm-s-inner.cm-link { color: rgb(0, 0, 204); } .cm-negative { color: rgb(221, 68, 68); } .cm-positive { color: rgb(34, 153, 34); } .cm-header, .cm-strong { font-weight: 700; } .cm-del { text-decoration: line-through; } .cm-em { font-style: italic; } .cm-link { text-decoration: underline; } .cm-error { color: red; } .cm-invalidchar { color: red; } .cm-constant { color: rgb(38, 139, 210); } .cm-defined { color: rgb(181, 137, 0); } div.CodeMirror span.CodeMirror-matchingbracket { color: rgb(0, 255, 0); } div.CodeMirror span.CodeMirror-nonmatchingbracket { color: rgb(255, 34, 34); } .cm-s-inner .CodeMirror-activeline-background { background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; background-position: inherit; background-repeat: inherit; } .CodeMirror { position: relative; overflow: hidden; } .CodeMirror-scroll { height: 100%; outline: 0px; position: relative; box-sizing: content-box; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: inherit; background-position: inherit; background-repeat: inherit; } .CodeMirror-sizer { position: relative; } .CodeMirror-gutter-filler, .CodeMirror-hscrollbar, .CodeMirror-scrollbar-filler, .CodeMirror-vscrollbar { position: absolute; z-index: 6; display: none; outline: 0px; } .CodeMirror-vscrollbar { right: 0px; top: 0px; overflow: hidden; } .CodeMirror-hscrollbar { bottom: 0px; left: 0px; overflow: auto hidden; } .CodeMirror-scrollbar-filler { right: 0px; bottom: 0px; } .CodeMirror-gutter-filler { left: 0px; bottom: 0px; } .CodeMirror-gutters { position: absolute; left: 0px; top: 0px; padding-bottom: 10px; z-index: 3; overflow-y: hidden; } .CodeMirror-gutter { white-space: normal; height: 100%; box-sizing: content-box; padding-bottom: 30px; margin-bottom: -32px; display: inline-block; } .CodeMirror-gutter-wrapper { position: absolute; z-index: 4; border: none !important; background-position: 0px 0px !important; } .CodeMirror-gutter-background { position: absolute; top: 0px; bottom: 0px; z-index: 4; } .CodeMirror-gutter-elt { position: absolute; cursor: default; z-index: 4; } .CodeMirror-lines { cursor: text; } .CodeMirror pre { border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; border-width: 0px; font-family: inherit; font-size: inherit; margin: 0px; white-space: pre; word-wrap: normal; color: inherit; z-index: 2; position: relative; overflow: visible; background-position: 0px 0px; } .CodeMirror-wrap pre { word-wrap: break-word; white-space: pre-wrap; word-break: normal; } .CodeMirror-code pre { border-right-width: 30px; border-right-style: solid; border-right-color: transparent; width: fit-content; } .CodeMirror-wrap .CodeMirror-code pre { border-right-style: none; width: auto; } .CodeMirror-linebackground { position: absolute; inset: 0px; z-index: 0; } .CodeMirror-linewidget { position: relative; z-index: 2; overflow: auto; } .CodeMirror-wrap .CodeMirror-scroll { overflow-x: hidden; } .CodeMirror-measure { position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden; } .CodeMirror-measure pre { position: static; } .CodeMirror div.CodeMirror-cursor { position: absolute; visibility: hidden; border-right-style: none; width: 0px; } .CodeMirror div.CodeMirror-cursor { visibility: hidden; } .CodeMirror-focused div.CodeMirror-cursor { visibility: inherit; } .cm-searching { background-color: rgba(255, 255, 0, 0.4); } span.cm-underlined { text-decoration: underline; } span.cm-strikethrough { text-decoration: line-through; } .cm-tw-syntaxerror { color: rgb(255, 255, 255); background-color: rgb(153, 0, 0); } .cm-tw-deleted { text-decoration: line-through; } .cm-tw-header5 { font-weight: 700; } .cm-tw-listitem:first-child { padding-left: 10px; } .cm-tw-box { border-style: solid; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-color: inherit; border-top-width: 0px !important; } .cm-tw-underline { text-decoration: underline; } @media print { .CodeMirror div.CodeMirror-cursor { visibility: hidden; } } :root { --side-bar-bg-color: #fafafa; --control-text-color: #777; } @include-when-export url(https://fonts.loli.net/css?family=Open+Sans:400italic,700italic,700,400&subset=latin,latin-ext); /* open-sans-regular - latin-ext_latin */ /* open-sans-italic - latin-ext_latin */ /* open-sans-700 - latin-ext_latin */ /* open-sans-700italic - latin-ext_latin */ html { font-size: 16px; -webkit-font-smoothing: antialiased; } body { font-family: "Open Sans","Clear Sans", "Helvetica Neue", Helvetica, Arial, 'Segoe UI Emoji', sans-serif; color: rgb(51, 51, 51); line-height: 1.6; } #write { max-width: 860px; margin: 0 auto; padding: 30px; padding-bottom: 100px; } @media only screen and (min-width: 1400px) { #write { max-width: 1024px; } } @media only screen and (min-width: 1800px) { #write { max-width: 1200px; } } #write > ul:first-child, #write > ol:first-child{ margin-top: 30px; } a { color: #4183C4; } h1, h2, h3, h4, h5, h6 { position: relative; margin-top: 1rem; margin-bottom: 1rem; font-weight: bold; line-height: 1.4; cursor: text; } h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor { text-decoration: none; } h1 tt, h1 code { font-size: inherit; } h2 tt, h2 code { font-size: inherit; } h3 tt, h3 code { font-size: inherit; } h4 tt, h4 code { font-size: inherit; } h5 tt, h5 code { font-size: inherit; } h6 tt, h6 code { font-size: inherit; } h1 { font-size: 2.25em; line-height: 1.2; border-bottom: 1px solid #eee; } h2 { font-size: 1.75em; line-height: 1.225; border-bottom: 1px solid #eee; } /*@media print { .typora-export h1, .typora-export h2 { border-bottom: none; padding-bottom: initial; } .typora-export h1::after, .typora-export h2::after { content: ""; display: block; height: 100px; margin-top: -96px; border-top: 1px solid #eee; } }*/ h3 { font-size: 1.5em; line-height: 1.43; } h4 { font-size: 1.25em; } h5 { font-size: 1em; } h6 { font-size: 1em; color: #777; } p, blockquote, ul, ol, dl, table{ margin: 0.8em 0; } li>ol, li>ul { margin: 0 0; } hr { height: 2px; padding: 0; margin: 16px 0; background-color: #e7e7e7; border: 0 none; overflow: hidden; box-sizing: content-box; } li p.first { display: inline-block; } ul, ol { padding-left: 30px; } ul:first-child, ol:first-child { margin-top: 0; } ul:last-child, ol:last-child { margin-bottom: 0; } blockquote { border-left: 4px solid #dfe2e5; padding: 0 15px; color: #777777; } blockquote blockquote { padding-right: 0; } table { padding: 0; word-break: initial; } table tr { border: 1px solid #dfe2e5; margin: 0; padding: 0; } table tr:nth-child(2n), thead { background-color: #f8f8f8; } table th { font-weight: bold; border: 1px solid #dfe2e5; border-bottom: 0; margin: 0; padding: 6px 13px; } table td { border: 1px solid #dfe2e5; margin: 0; padding: 6px 13px; } table th:first-child, table td:first-child { margin-top: 0; } table th:last-child, table td:last-child { margin-bottom: 0; } .CodeMirror-lines { padding-left: 4px; } .code-tooltip { box-shadow: 0 1px 1px 0 rgba(0,28,36,.3); border-top: 1px solid #eef2f2; } .md-fences, code, tt { border: 1px solid #e7eaed; background-color: #f8f8f8; border-radius: 3px; padding: 0; padding: 2px 4px 0px 4px; font-size: 0.9em; } code { background-color: #f3f4f4; padding: 0 2px 0 2px; } .md-fences { margin-bottom: 15px; margin-top: 15px; padding-top: 8px; padding-bottom: 6px; } .md-task-list-item > input { margin-left: -1.3em; } @media print { html { font-size: 13px; } table, pre { page-break-inside: avoid; } pre { word-wrap: break-word; } } .md-fences { background-color: #f8f8f8; } #write pre.md-meta-block { padding: 1rem; font-size: 85%; line-height: 1.45; background-color: #f7f7f7; border: 0; border-radius: 3px; color: #777777; margin-top: 0 !important; } .mathjax-block>.code-tooltip { bottom: .375rem; } .md-mathjax-midline { background: #fafafa; } #write>h3.md-focus:before{ left: -1.5625rem; top: .375rem; } #write>h4.md-focus:before{ left: -1.5625rem; top: .285714286rem; } #write>h5.md-focus:before{ left: -1.5625rem; top: .285714286rem; } #write>h6.md-focus:before{ left: -1.5625rem; top: .285714286rem; } .md-image>.md-meta { /*border: 1px solid #ddd;*/ border-radius: 3px; padding: 2px 0px 0px 4px; font-size: 0.9em; color: inherit; } .md-tag { color: #a7a7a7; opacity: 1; } .md-toc { margin-top:20px; padding-bottom:20px; } .sidebar-tabs { border-bottom: none; } #typora-quick-open { border: 1px solid #ddd; background-color: #f8f8f8; } #typora-quick-open-item { background-color: #FAFAFA; border-color: #FEFEFE #e5e5e5 #e5e5e5 #eee; border-style: solid; border-width: 1px; } /** focus mode */ .on-focus-mode blockquote { border-left-color: rgba(85, 85, 85, 0.12); } header, .context-menu, .megamenu-content, footer{ font-family: "Segoe UI", "Arial", sans-serif; } .file-node-content:hover .file-node-icon, .file-node-content:hover .file-node-open-state{ visibility: visible; } .mac-seamless-mode #typora-sidebar { background-color: #fafafa; background-color: var(--side-bar-bg-color); } .md-lang { color: #b4654d; } /*.html-for-mac { --item-hover-bg-color: #E6F0FE; }*/ #md-notification .btn { border: 0; } .dropdown-menu .divider { border-color: #e5e5e5; opacity: 0.4; } .ty-preferences .window-content { background-color: #fafafa; } .ty-preferences .nav-group-item.active { color: white; background: #999; } .menu-item-container a.menu-style-btn { background-color: #f5f8fa; background-image: linear-gradient( 180deg , hsla(0, 0%, 100%, 0.8), hsla(0, 0%, 100%, 0)); } :root {--mermaid-font-zoom:1em ;} @media print { @page {margin: 0 0 0 0;} body.typora-export {padding-left: 0; padding-right: 0;} #write {padding:0;}} 技术概要:使用 InterSystems 产品优化 SQL 性能使用 InterSystems SQL 优化查询使用 EXPLAIN 关键字显示查询计划在管理门户(Management Portal)中使用 SQL 查询接口显示查询计划发现查询计划结果中潜在的性能问题测试查询执行测试位片索引(Bitslice Index)的效果向交易类型字段(TransactionType Field)添加位图索引(Bitmap Index)重新测试查询性能查看随时间变化的查询性能了解有关 InterSystems SQL 的更多信息介绍材料 技术概要:使用 InterSystems 产品优化 SQL 性能 技术概要:使用 InterSystems 产品优化 SQL 性能 本技术概要(First Look)指南向您介绍了 InterSystems SQL 查询优化,包括查询分析工具的使用,几种索引方法以及随着时间的变化查看运行时统计数据的能力。 要浏览所有的技术概要(First Look),包括其他可以在免费的云实例或 web 实例上执行的技术概要(First Look),请参见 InterSystems First Looks(《InterSystems 技术概要》)。 使用 InterSystems SQL 优化查询 InterSystems IRIS®数据平台为 SQL 查询性能调整提供全套工具: 查询计划分析的图形化显示 如位图和位片索引(bitslice index)等索引策略结构紧凑,可由矢量化 CPU 指令有效处理。每种索引类型都为某些查询类型(如逻辑条件、计数和聚合函数)提供了好处。通过索引,您可以在一个核心上实现每秒多达数十亿行的查询性能结果。 随时间变化的 SQL 查询性能指标 重要提示: 下面演示中显示的查询性能数字代表了在一台 Windows 10 笔记本电脑上进行的多次演示试验。根据您的环境,您可能会看到不同的查询性能数字。 想查看 InterSystems IRIS SQL 功能快速演示吗?请查看 SQL QuickStart(SQL 快速入门)! 用前须知 阅读本文之前,建议阅读并完成 First Look:InterSystems SQL(《技术概要:InterSystems SQL》)。在这里,您将再次使用 InterSystems IRIS SQL Shell;您将使用的数据来自您在技术概要:InterSystems SQL的演示时创建的百万记录股票交易数据表。 您还将运行 TuneTableutility,它检查表中的数据并创建 InterSystems SQL 查询优化器(决定如何最好地运行任何查询的引擎)使用的统计数据。这些统计数据包括表的大小(区段大小)和每列唯一值的数量(选择性)。优化器在决定连接顺序等情况下使用表大小,其中最好从较小的表开始。在表有多个索引的情况下,选择性有助于优化器选择最佳索引。在产品实例中,您通常只运行一次 TuneTable:在数据被加载到表中之后和运行之前。 演示:显示和解释优化前的查询计划 First Look:InterSystems SQL (《技术概要:InterSystems SQL》)解释了如何执行在技术概要(First Look)和此处运行演示所需的以下步骤: 选择一个 InterSystems IRIS 实例。您的选择包括多种类型的已授权的和免费的评估实例;关于如何部署每种类型的信息,请参见 InterSystems IRIS Basics: Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中的 Deploying InterSystems IRIS(部署 InterSystems IRIS)。 打开 InterSystems 终端(Terminal)(简称终端(Terminal))来运行 SQL Shell。 从 GitHub repo https://github.com/intersystems/FirstLook-SQLBasics 获取本指南的实用程序文件和数据,包括 stock_table_demo_two.csv,其中包含一百万行股票表数据 Loader.xml,是一个包含实用程序方法的类文件,用于将 Stock_table_demo_two.csv 中的数据加载到InterSystems IRIS 表中。 运行 TuneTable 实用程序 如果您的 InterSystems IRIS 实例不再包含 StockTableDemoTwotable,请按照 Demo:Using Bitmap Indexing To Maximize Query Performance(《演示:使用位图索引最大化查询性能》)(在执行 SELECT DISTINCT 查询之前停止)的前四个步骤重新创建并加载它。 在 SQL Shell 中,在 FirstLook.StockTableDemoTwo 上运行 TuneTable 实用程序,如下所示: OBJ DO $SYSTEM.SQL.TuneTable("FirstLook.StockTableDemoTwo") 该命令在 SQL Shell 中不会生成可见的输出。 使用 EXPLAIN 关键字显示查询计划 这个演示假设您想获得所有"SELL"交易的平均价格。鉴于该表包含一百万条记录,所需的查询有可能非常慢。 虽然您可能已经想在 Price 和 TransactionType 字段上创建索引,但在开始优化工作之前,查看查询计划将具有指导意义。在 SQL Shell 中,您可以通过在查询前添加 EXPLAIN 关键字来显示查询计划。查询计划显示 SQL 查询优化器将如何使用索引(如果有索引的话),或者是否将直接读取表数据来执行语句。 要使用 EXPLAIN 关键字来显示查询计划,在 SQL Shell 中执行以下语句: EXPLAIN SELECT AVG(Price) As AveragePrice FROM FirstLook.StockTableDemoTwo WHERE TransactionType = 'SELL' 这将返回格式为 XML 的查询计划: xxxxxxxxxx Plan "<plans> <plan> <sql> SELECT AVG ( Price ) AS AveragePrice FROM FirstLook . StockTableDemoTwo WHERE TransactionType = ? /*#OPTIONS {""DynamicSQLTypeList"":""1""} */ </sql> <cost value=""1827000""/> Call module B. Output the row. <module name=""B"" top=""1""> Process query in parallel, partitioning master map FirstLook.StockTableDemoTwo.IDKEY into subranges of T1.ID values, piping results to temp-file A: SELECT count(T1.Price),sum(T1.Price) FROM %NOPARALLEL FirstLook.StockTableDemoTwo T1 where ((%SQLUPPER(T1.TransactionType) = %SQLUPPER(?))) Read temp-file A, looping on a counter. For each row: Accumulate the count([value]). Accumulate the sum([value]). </module> 演示:显示和解释优化前的查询计划 </plan> <plan> <sql> SELECT COUNT ( T1 . Price ) , SUM ( T1 . Price ) FROM %NOPARALLEL FirstLook . StockTableDemoTwo T1 WHERE ( ( %SQLUPPER ( T1 . TransactionType ) = %SQLUPPER ( ? ) ) ) %PARTITION BY T1 . ID > ? AND T1 . ID <= ? </sql> <cost value=""1827000""/> Call module B. Output the row. <module name=""B"" top=""1""> Read master map FirstLook.StockTableDemoTwo.IDKEY, looping on ID (with a range condition). For each row: Accumulate the count(Price). Accumulate the sum(Price). </module> </plan> </plans>" 您将看到为执行 SQL 查询而生成的查询计划可以分为多个模块,每个模块都执行计划的不同部分,例如评估子查询。 实际上,这个查询计划被分为两个独立的计划。顶部计划用于初始查询。它调用一个模块 B,在这个模块中,其中"主映射"被分区,并在每个分区上并行执行子查询。子查询的计划遵循初始查询的计划。 在 "Spotting Potential Performance Issues in Query Plan Results(在查询计划结果中发现潜在的性能问题)"中,您将学习如何识别这个查询的问题。 在管理门户(Management Portal)中使用 SQL 查询接口显示查询计划 InterSystems IRIS 在管理门户(Management Portal)中提供了一个基于 web 的接口,用于 SQL 查询执行和计划分析。要使用管理门户(Management Portal)中的 SQL 查询接口显示查询计划: 使用 InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中URL described for your instance(为您的实例描述的 URL),在浏览器中打开您的实例的管理门户(Management Portal)。 请确保您是在 USER 命名空间。 如果您还没有找到,可以: 在屏幕的顶部面板中,点击当前命名空间名称右侧的 SWITCH(交换)。 在弹出的窗口中,选择 USER(用户) 并点击 OK(确定)。 导航到 SQL 页面(System Explorer(系统资源管理器) > SQL)。 省略 EXPLAIN 关键字,将"Using the EXPLAIN Keyword to Show a Query Plan(使用 EXPLAIN 关键字显示查询计划)中的查询粘贴到 Execute Query(执行查询) 标签的文本字段中。 点击 Show Plan(显示计划) 来显示查询计划。 结果将如下所示: 解释这些结果是下一节的主题。 发现查询计划结果中潜在的性能问题 查看查询计划结果,您可以看到这个查询存在一些严重的潜在性能问题。如果您查看子查询的计划,也就是实际工作完成的地方,您可以看到第一个任务是 "读取主映射"。这意味着 InterSystems SQL 查询优化器不会使用任何索引来运行查询; 演示:测试查询优化 相反,查询将遍历表中的所有 ID。特别是在大表的情况下,这表明查询将不能很好地执行。 当您优化查询时,您会看到它的执行时间减少,查询计划也会有明显的变化。 注意: 相对成本可以很好地预测性能,但只是相对于某个特定的查询而言。如果您在表中添加了一个索引,并且看到相对成本下降了,那么很可能这个查询现在会运行得更快。然而,相对成本并不是为了比较两个不同查询的性能。 测试查询执行 要获取有关未优化查询将如何执行的一些实际数据,请在 SQL Shell 中运行它: SELECT AVG(Price) As AveragePrice FROM FirstLook.StockTableDemoTwo WHERE TransactionType = 'SELL' GO 输出将如下所示: xxxxxxxxxx AveragePrice 266.1595139195757844 1 Rows(s) Affected statement prepare time(s)/globals/cmds/disk: 0.0009s/6/1246/0ms execute time(s)/globals/cmds/disk: 0.2599s/1000075/8502571/0ms cached query class: %sqlcq.USER.cls5 语句准备和执行指标分别列出。特别注意以下两项: 执行时间为 0.2599 秒。虽然这个时间看起来并不算长,但可以通过使用索引大大改善。 在执行步骤中读取的 globals 数量为 1,000,075。(Globals 是 InterSystems IRIS 用来存储数据的多维稀疏数组(multidimensional sparse arrays);更多信息,请参见 Introduction to InterSystems IRIS Programming(《InterSystems IRIS 编程简介》)中的Introduction to Globals(Globals 简介)一章。为了提高查询性能,应该减少这个数字。您会在下一节看到这种情况。 重要提示: 准备工作只需一次:第一次重新规划查询。如果修改了相关表或添加或删除了索引,查询将自动重新规划。大多数应用程序只准备一次查询,但会多次执行。因此,在这个演示中,我们的重点将是调整执行性能。 演示:测试查询优化 向价格字段添加位片索引(Bitslice Index) 如果您的查询将包含一个或多个字段上的聚合函数,那么为这些字段中的一个或多个字段添加位片索引(bitslice index)可能会提高性能。 位片索引(bitslice index)将字段中的每个数字数据值表示为二进制位字符串,二进制值中的每个数字都有一个位图,以记录哪些行的二进制数字为 1。 因为我们想要获得所有"SELL"交易的平均价格,所以在 Price 字段中添加一个位片索引(bitslice index)是有意义的。要在 Price 字段上创建位片索引(bitslice index) PriceIdx,请在 SQL Shell 中执行以下语句: 演示:测试查询优化 CREATE BITSLICE INDEX PriceIdx ON TABLE FirstLook.StockTableDemoTwo (Price) CREATE BITSLICE INDEX PriceIdx ON TABLE FirstLook.StockTableDemoTwo (Price) xxxxxxxxxx 0 Rows Affected statement prepare time(s)/globals/cmds/disk: 0.0091s/2000/13151/0ms execute time(s)/globals/cmds/disk: 1.4268s/2087789/55765062/1ms cached query class: %sqlcq.USER.cls7 但是,正如您将在下面看到的,仅仅因为您创建了索引并不一定意味着 InterSystems SQL 查询优化器会使用它 。 测试位片索引(Bitslice Index)的效果 要查看新的位片索引(bitslice index)是否会对查询的执行方式或运行速度产生任何影响,请使用上述任何一种方法(SQL Shell 或管理门户(Management Portal))来显示查询计划。 正如您将看到的,查询计划仍然与以前相同。InterSystems SQL 查询优化器将不会使用新的索引。 运行查询产生的性能统计数据与您创建位片索引(bitslice index)之前几乎相同(0.2559 秒的执行时间与 0.2599 秒相比)。InterSystems IRIS 智能地缓存查询计划和数据,因此同一查询的后续运行可能会提高性能,鉴于查询性能时间略有不同,这里可能就是这种情况。 在机器上运行的其他应用程序也会影响性能。 SELECT AVG(Price) As AveragePrice FROM FirstLook.StockTableDemoTwo WHERE TransactionType = 'SELL' GO SELECT AVG(Price) As AveragePrice FROM FirstLook.StockTableDemoTwo WHERE TransactionType = 'SELL' xxxxxxxxxx AveragePrice 266.1595139195757844 1 Rows(s) Affected statement prepare time(s)/globals/cmds/disk: 0.0569s/35431/227191/0ms execute time(s)/globals/cmds/disk: 0.2559s/1000075/8502571/0ms cached query class: %sqlcq.USER.cls8 如果从查询中删除 WHERE 子句,当您显示查询计划时,将会看到完全不同的结果: 如您所见,读取位片索引(bitslice index)是查询计划的第一步。在这个计划中没有读取到"总映射"。 SQL 查询优化器也使用第二个索引 FirstLook.StockTableDemoTwo.$StockTableDemoTwo。这是位图范围索引, 在执行 CREATE TABLESQL 语句时自动创建。它是表中所有行的位图索引(bitmap index),而不仅仅是一个字段,每个位的值反映了该行是否实际存在。 演示:测试查询优化 然而,我们真正想要运行的查询包含一个 WHERE 子句。因此,我们必须找到一种方法,让 SQL 查询优化器在 WHERE 子句存在时使用索引。 向交易类型字段(TransactionType Field)添加位图索引(Bitmap Index) 如果您阅读了 InterSystems SQL Optimization Guide(《InterSystems SQL 优化指南》),您会发现 InterSystems SQL 查询优化器在与 WHERE 子句字段上的位图索引(bitmap index)结合使用时,通常会使用位片索引(bitslice index)。 这是因为没有 WHERE 子句的聚合查询可以简单地聚合索引中的所有数据。然而,为了只聚合满足 WHERE 条件的行,查询必须掩码那些不满足条件的行的位片索引(bitslice index)的位。在 WHERE 子句中的字段上有一个位图索引(bitmap index),允许有效地构建这个掩码。 幸运的是,查询中的另一个字段 TransactionType 是位图索引(bitmap index)的一个很好的候选者,因为它的可能值计数是两个("SELL"和"BUY")。 要向 TransactionType 字段添加位图索引(bitmap index),请在 SQL Shell 中执行以下语句: CREATE BITMAP INDEX TransactionTypeIdx ON TABLE FirstLook.StockTableDemoTwo (TransactionType) CREATE BITMAP INDEX TransactionTypeIdx ON TABLE FirstLook.StockTableDemoTwo (TransactionType) xxxxxxxxxx 0 Rows Affected statement prepare time(s)/globals/cmds/disk: 0.0069s/2001/13291/0ms execute time(s)/globals/cmds/disk: 1.1046s/2088960/19771584/0ms cached query class: %sqlcq.USER.cls7 重新测试查询性能 现在,您已经添加了位片索引(bitslice index)和位图索引(bitmap index):如果您显示的查询计划 SELECT AVG(Price) as AveragePrice FROM FirstLook.StockTableDemoTwo WHERE TransactionType = 'SELL' 在 SQL Shell 或管理门户(Management Portal)中,您会看到查询优化器使用您创建的两个索引来获得最佳性能。 还请注意,18742 的相对成本只是未优化查询的一小部分,其成本为 1827000。 演示:测试查询优化 最后,如果您在 SQL Shell 中运行这个查询,您会看到对 globals 的更有效使用(594 而不是 1000075)。 最关键的是,有索引的查询运行速度比无索引的查询快了近 85 倍(执行时间为 0.0031 秒,而非 0.2599)。 查看随时间变化的查询性能 SELECT AVG(Price) As AveragePrice FROM FirstLook.StockTableDemoTwo WHERE TransactionType = 'SELL' GO SELECT AVG(Price) As AveragePrice FROM FirstLook.StockTableDemoTwo WHERE TransactionType = 'SELL' xxxxxxxxxx AveragePrice 266.1595139195757844 1 Rows(s) Affected statement prepare time(s)/globals/cmds/disk: 0.0554s/34877/186130/0ms execute time(s)/globals/cmds/disk: 0.0031s/594/2878/0ms cached query class: %sqlcq.USER.cls8 为了随时间跟踪查询的性能,InterSystems IRIS 提供了查询统计数据,您将在下一节了解如何查看这些数据。 查看随时间变化的查询性能 要跟踪运行缓慢的查询或查看新查询在产品中的运行情况,您可以使用管理门户(Management Portal)中的 SQL Statements(SQL 语句)视图。要导航到这个视图,在管理门户(Management Portal)中打开 SQL 查询接口,并点击 SQL Statements(SQL语句)。 例如,如果您上面调整的查询在其原始(未优化的)计划下运行了 9 次,您可能会看到类似这样的结果: 点击 SQL Statement Text column(SQL 语句文本列)中的语句链接, 允许您以 SQL 形式查看查询: 您还可以使用缓存查询类的名称将 SQL 语句执行与 SQL Statements(SQL 语句)视图联系起来,该名称是 SQL Shell 中输出的最后一行,并列在 SQL Statements(SQL 语句) 的 Location(s)(位置)列中。 在您优化查询并运行几次后,您可以期望看到 Total time(总时间)和 Average time(平均时间)的改善列。 了解有关 InterSystems SQL 的更多信息 请注意,Count(计数)的值已经下降。这是因为位图和位片索引(bitslice index)的添加引起了查询计划的改变,这反过来又触发了对相关类的缓存查询的删除。该查询在新查询计划下总共运行了 8 次,平均每天 4 次。 了解有关 InterSystems SQL 的更多信息 要了解更多有关 SQL 和 InterSystems IRIS 的信息,请参见: 介绍材料 First Look:InterSystems SQL(《技术概要:InterSystems SQL》) Using InterSystems SQL(《使用 InterSystems SQL》) InterSystems SQL Reference(《InterSystems SQL 参考书目》) InterSystems SQL Overview(《InterSystems SQL 概述》) SQL 开发 SQL -- Things You Should Know(《SQL -- 您应该知道的事情》) Developing with InterSystems Objects and SQL(《使用 InterSystems Objects 和 SQL 开发》) 查询优化 InterSystems SQL Optimization Guide(《InterSystems SQL 优化指南》) Optimizing SQL Queries(《优化 SQL 查询》) 分片和可扩展性 First Look:Scaling for Data Volume with Sharding(《技术概要:带分片的数据卷扩展》) Scalability Guide(《可扩展性指南》) SQL 搜索 First Look:SQL Search with InterSystems IRIS(《技术概要:使用 InterSystems IRIS 进行 SQL 搜索》) Using InterSystems SQL Search(《使用 InterSystems SQL 搜索》) Creating iFind Indices for Searching Text Fields(《创建用于搜索文本字段的 iFind 索引》) JDBC First Look:JDBC and InterSystems IRIS (《技术概要:JDBC 和 InterSystems IRIS》) Using Java JDBC with InterSystems IRIS(《在 InterSystems IRIS 中使用 Java JDBC》)<文档> Java Overview (《Java 概述》) 了解有关 InterSystems SQL 的更多信息 Using JDBC with InterSystems IRIS(《在 InterSystems IRIS 中使用 JDBC》) <在线学习>
文章
jieliang liu · 九月 22, 2021

IRIS 2021 技术文档 First Look 9--ADO.NET 和 InterSystems 产品

技术概要:ADO.NET 和 InterSystems 产品 本技术概要(First Look)解释了如何通过 InterSystems ADO.NET Managed Provider 连接到 InterSystems IRIS®数据平台。一旦根据本指南完成操作,就意味着您已经配置了一个 Visual Studio 项目来使用 InterSystems.Data.IRISClient.dll 程序集,建立了到 InterSystems IRIS 的 ADO.NET 连接,从您的 .NET 应用程序运行多个 SQL 语句,并在 InterSystems IRIS 系统管理门户(InterSystems IRIS System Management Portal)中确认这些语句的效果。 为了让您体验一下 ADO.NET Managed Provider,而又不陷入细节的困境,我们会确保这一探索简洁可行。这些活动被设计成只使用默认设置和功能,这样您就可以熟悉功能的基本原理,而不必处理那些离题或过于复杂的细节。当您将 ADO.NET 引入您的生产系统时,您可能需要做一些不同的事情。请确保不要把这种对 ADO.NET 的探索与真实的东西混淆起来! 本文档末尾提供的参考资料将使您对在生产中使用 ADO.NET 所涉及的内容有一个很好的了解。 有关 ADO.NET 的更多文档,请参见结尾处的 Learn More About ADO.NET(了解更多有关 ADO.NET 的信息)。 要浏览所有的技术概要(First Look),包括可以在 InterSystems IRIS 免费的评估实例上执行的那些,请参见 InterSystems First Looks(《InterSystems 技术概要》)。 为什么 ADO.NET 很重要 ADO.NET 是来自 Microsoft .NET Framework 的数据访问技术,提供对数据源的访问。它用于建立数据库连接,并为 .NET Framework 程序员提供一种标准、可靠的方式,来连接到多种类型的数据源或使用 SQL 对它们进行操作。通过 ADO.NET Managed Provider 连接到 InterSystems IRIS 很简单,特别是如果您以前使用过 ADO.NET。从 .NET 应用程序建立到 InterSystems IRIS 的 ADO.NET 连接,允许您从 .NET 应用程序对 InterSystems IRIS 数据库运行 SQL 命令。 如果您是 InterSystems IRIS 的新手,但熟悉 .NET 和 SQL,您可以立即使用现有的专业知识来帮助您熟悉数据库平台。您可以在开发环境中测试 ADO.NET 连接和 SQL 命令,只需几行代码。 ADO.NET 和 InterSystems IRIS InterSystems IRIS 是完全符合 ADO.NET 规范的实现。InterSystems ADO.NET Managed Provider 提供对数据的简单关系访问。它处理来自应用程序的 ADO.NET 方法调用,并向 InterSystems IRIS 提交 SQL 请求。然后将结果返回给调用的应用程序------在本例中,就是您的 .NET 应用程序。 通过 ADO.NET 连接到 InterSystems IRIS 是一个非常简单的过程。 为了使用 InterSystems IRIS ADO.NET 功能,您必须首先将 InterSystems.Data.IRISClient.dll 程序集作为依赖项添加到 Visual Studio 项目中。确认一些设置后,使用我们的示例代码建立到 InterSystems IRIS 的 ADO.NET 探索 ADO.NET 连接,并执行 SQL 查询。请注意,InterSystems.Data.IRISClient.dll 程序集自始至终都是使用 .NET 管理代码实现的,这使得在 .NET 环境中部署它很容易。它是线程安全(thread-safe)的 ,可以在多线程的 .NET 应用程序中使用。 探索 ADO.NET 我们开发了一个简短的演示,向您展示如何使用 ADO.NET 和 InterSystems IRIS。(想试试 InterSystems IRIS .NET 开发和互操作性功能的在线视频演示?请看.NET QuickStart(.NET 快速入门)!) 用前须知 要使用这个程序,您需要一个安装了 .NET 框架和 Visual Studio 的 Windows 系统,以及一个运行中的 InterSystems IRIS 实例来连接。您对 InterSystems IRIS 的选择包括多种类型的已授权的和免费的评估实例;实例不需要由您正在工作的系统托管(尽管它们必须相互具有网络访问权限)。有关如何部署每种类型的实例的信息(如果您还没有可使用的实例) ,请参见 InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中的 Deploying InterSystems IRIS(部署 InterSystems IRIS)。使用同一文档中的 InterSystems IRIS Connection Information(InterSystems IRIS 连接信息)和 .Net IDE 中的信息将 Visual Studio 连接到您的 InterSystems IRIS 实例。 配置 Visual Studio 项目 在 Visual Studio 主菜单中,通过选择 File(文件) > New (新的)> Project(项目)创建一个新项目。在出现的对话框中,点击 Visual C# 选项,并选择 Console App (.NET Framework)(控制台应用程序(.NET 框架))。对于 Name(名称) 字段,输入 ADONET。点击 OK(確定)。这将使用 .NET Framework 创建一个新的控制台(console)应用程序。 下一步,在 Visual Studio 主菜单中,选择 Project(项目) > ADONET Properties(ADONET 属性)。在 Target framework(目标框架)下,选择 .NET Framework 4.5(.NET 框架 4.5)。 添加程序集引用 InterSystems.Data.IRISClient.dll 程序集必须安装在您的本地系统上。您可以通过克隆 repo https://github.com/intersystems/quickstarts-dotnet/tree/master/EFPlay/bin/Debug 或从该 repo 下载文件来获取它。如果 InterSystems IRIS 安装在您的本地系统或您可以访问的另一个系统上,则该程序集已经安装在子目录 install-dirdevdotnetbinv4.5 中,其中 install-dir 是该实例的安装目录。 要将 InterSystems.Data.IRISClient.dll 的程序集引用添加到项目: 从 Visual Studio 主菜单中,选择 Project(项目) > Add Reference(添加引用)... 在出现的窗口中,点击 Browse(浏览).... 浏览到 InterSystems.Data.IRISClient.dll 文件的位置。 选择文件并点击 Add(添加)。 点击 OK(確定)。 在 Visual Studio Solution Explorer 中, InterSystems.Data.IRISClient.dll 程序集现在应该列在 Reference(引用)下。 探索 ADO.NET 通过 ADO.NET 连接 现在,您可以从 .NET 应用程序连接到 InterSystems IRIS 了。InterSystems ADO.NET Managed Provider 的连接字符串是由定义连接属性的键/值对组成的。连接字符串的语法是: Server=host_IP; Port=superserverPort; Namespace=namespace; Password=password; User ID=username; 其中的变量表示 InterSystems IRIS 实例主机的 IP 地址、实例的超级服务器端口、实例上的命名空间和实例的凭据(credentials)。这与您在连接 Visual Studio 到您的实例时使用的信息相同,如用前须知中所述。 将其粘贴到 Visual Studio 后,在随后的代码中更新该信息。您可以将命名空间设置为预定义的命名空间 USER,如所示,或者设置为您在已安装的实例上创建的另一个命名空间。 using System; ​ using InterSystems.Data.IRISClient; ​ namespace ADONET ​ { ​ class Program ​ { ​ static void Main(string[] args) ​ { ​ String host = "<host>"; String port = "<port>"; ​ String username = "<username>"; String password = "<password>"; String Namespace = "USER"; ​ IRISConnection IRISConnect = new IRISConnection(); IRISConnect.ConnectionString = "Server = " + host ​ + "; Port = " + port + "; Namespace = " + Namespace ​ + "; Password = " + password + "; User ID = " + username; ​ IRISConnect.Open(); ​ String sqlStatement1 = "CREATE TABLE People(ID int, FirstName varchar(255), LastName varchar(255))"; ​ String sqlStatement2 = "INSERT INTO People VALUES (1, 'John', 'Smith')"; String sqlStatement3 = "INSERT INTO People VALUES (2, 'Jane', 'Doe')"; String queryString = "SELECT * FROM People"; ​ IRISCommand cmd1 = new IRISCommand(sqlStatement1, IRISConnect); IRISCommand cmd2 = new IRISCommand(sqlStatement2, IRISConnect); IRISCommand cmd3 = new IRISCommand(sqlStatement3, IRISConnect); IRISCommand cmd4 = new IRISCommand(queryString, IRISConnect); ​ //ExecuteNonQuery() is used for CREATE, INSERT, UPDATE, and DELETE SQL Statements cmd1.ExecuteNonQuery(); ​ cmd2.ExecuteNonQuery(); cmd3.ExecuteNonQuery(); ​ //ExecuteReader() is used for SELECT IRISDataReader Reader = cmd4.ExecuteReader(); ​ Console.WriteLine("Printing out contents of SELECT query: "); while (Reader.Read()) ​ { ​ + ", " ​ Console.WriteLine(Reader.GetValue(0).ToString() + ", " + Reader.GetValue(1).ToString() ​ + Reader.GetValue(2).ToString()); ​ } ​ Reader.Close(); cmd1.Dispose(); cmd2.Dispose(); cmd3.Dispose(); cmd4.Dispose(); IRISConnect.Close(); ​ Console.WriteLine("Press any key to continue..."); ​ Console.ReadKey(); ​ } ​ } ​ } 通过点击 Start(开始)按钮,或按 F5 键来运行代码。 如果连接和查询已经成功完成,您应该会看到一个控制台(console)窗口,其中包含 SELECT 查询的结果。 确认管理门户(Management Portal)的变更 接下来,使用以下程序在管理门户(Management Portal)中确认您的结果: 使用 InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中为您的实例描述的 URL ,在浏览器中打开您的实例的管理门户(Management Portal)。 如果您不在代码指定的命名空间中,请切换到该命名空间(点击页面顶部 Namespace(命名空间):指示器旁边的 Switch(切换))。 导航到 SQL 页面(System Explorer(系统资源管理器) > SQL),然后点击 Execute Query(执行查询)标签,并粘贴以下 SQL 查询: SELECT ID, FirstName, LastName FROM SQLUser.People 点击 Execute(执行)。该页面应该显示在示例代码中创建的 People 表的内容。 了解更多有关 ADO.NET 的信息 要了解更多有关 ADO.NET、SQL 和 InterSystems IRIS 的信息请参见: Using the InterSystems Managed Provider for .NET(《使用 .NET 的 InterSystems Managed Provider》) Using InterSystems SQL(《使用 InterSystems SQL》) ADO.NET Overview(《ADO.NET 概述》)
文章
Hao Ma · 十一月 2, 2021

IRIS 2021 技术文档 First Look 13 - InterSystems IRIS Native API for Java

本文档解释了如何使用 InterSystems IRIS Native 功能从 Java 应用程序中访问 InterSystems IRIS®数据平台的 globals。在本文中,您将首先连接到 InterSystems IRIS。然后您将在 InterSystems IRIS 中设置和检索一个 global 节点的值,并在另一个 global 节点上进行迭代。您还将调用 InterSystems IRIS 类方法。所有这些活动都将在 Java 应用程序中执行。为了让您体验 IRIS Native,而又不陷入细节困境,本次探索特意设计得很简单。这些活动被设计成只使用默认设置和功能,这样您就可以熟悉功能的基本原理,而不必处理那些离题或过于复杂的细节。当您把 IRIS Native 引入您的生产系统时,您可能需要做一些不同的事情。请确保不要把这种对 IRIS Native 的探索与真实的情况相混淆! 本文档末尾提供的参考资料将使您对在生产中使用 IRIS Native 的情况有一个很好的了解。要浏览所有的技术概要(First Look),包括可以在 InterSystems IRIS 免费的评估实例上执行的那些,请参见 InterSystems First Looks(《InterSystems 技术概要》)。 1 Globals 简介Globals 提供了一种易于使用的方式,来存储持久化多维数组中的数据。Global 是存储在 InterSystems IRIS 物理数据库中的命名多维数组。在应用程序中,globals 到物理数据库的映射基于当前命名空间,命名空间提供一个或多个物理数据库的逻辑统一视图。例如,要使用一个名为 ^Settings 的 global 将值 "Red"与键 "Color"关联起来,请使用 InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础: 连接一个 IDE》)中的procedure described for your instance(为您的实例描述的程序),打开 InterSystems 终端(InterSystems Terminal),并输入以下代码:set ^Settings("Color")="Red" 您可以利用 globals 的多维特性来定义一个更复杂的结构: set ^Settings("Auto1","Properties","Color") = "Red" set ^Settings("Auto1","Properties","Model") = "SUV" set ^Settings("Auto2","Owner") = "Mo"set ^Settings("Auto2","Properties","Color") = "Green" 有关 globals 的更多信息,请参见 Using Globals(《使用 globals》)。 2 为什么 IRIS Native 很重要?IRIS Native 是建立在 InterSystems IRIS JDBC 功能之上的一项功能,它允许您执行核心类 ObjectScript 命令的有限子集,并使用 globals 访问 InterSystems IRIS 数据,类似于在 InterSystems 终端(InterSystems Terminal)中使用的方式。该功能利用 JDBC 连接(JDBC connection)在 Java 应用程序中暴露(expose)核心 ObjectScript 功能。重要的是,由于 IRIS Native 使用与 JDBC 相同的连接,因此 InterSystems IRIS 数据通过 JDBC 作为关系表暴露(expose)给 Java 应用程序,通过 IRIS Native 作为 globals 暴露(expose)给 Java 应用程序。 探索 IRIS Native InterSystems IRIS 提供了一组独特的功能,可以使用相同的物理连接和事务环境来使用多个范例(本机、关系和面向对象)操作数据。 3 探索 IRIS Native以下向您简短演示如何在 Java 应用程序中使用 IRIS Native。(想试试 InterSystems IRIS Java 开发和互操作性功能的在线视频演示吗?请看 Java QuickStart(Java快速入门)!) 3.1 用前须知要使用该程序,您需要在一个系统上工作,安装 JDK 1.8 版本和您选择的 Java IDE,并连接一个正在运行的 InterSystems IRIS 实例。您对 InterSystems IRIS 的选择包括多种已授权的和免费的评估实例;实例不需要由您正在工作的系统托管(尽管它们必须相互具有网络访问权限)。关于如何部署每种类型的实例的信息(如果您还没有可使用的实例),请参见 InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中的 Deploying InterSystems IRIS(部署 InterSystems IRIS)。使用同一文档中的 InterSystems IRIS Connection Information(InterSystems IRIS 连接信息)和 Java IDE 中的信息,将 IDE 连接到您的 InterSystems IRIS 实例。您还需要将 InterSystems IRIS JDBC 驱动程序 intersystems-jdbc-3.0.0.jar 添加到您的本地 CLASSPATH。您可以从https://github.com/intersystems/quickstarts-java/tree/master/lib下载这个文件。如果您已经在本地系统或您能访问的另一个系统上安装了 InterSystems IRIS,您可以在 install-dir\dev\java\lib\JDK18 中找到该文件,其中 install-dir 是 InterSystems IRIS 的安装目录。3.2 连接 InterSystems IRIS InterSystems IRIS 连接字符串的语法是:jdbc:IRIS://host_IP:superserverPort/namespace,username,password其中的变量表示在 InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中connection settings described for your instance(为您的实例描述的连接设置)——这与您将 IDE 连接到实例时使用的信息相同。将命名空间设置为预定义的命名空间 USER,如下面的代码所示,或者设置为您在安装的实例中创建的另一个命名空间(只要您更新代码)。如果您连接到本地 Windows 系统上的实例(使用主机名 localhost 或 IP 地址 127.0.0.1),该连接会自动使用一种特殊的、高性能的本地连接,称为shared memory connection(共享内存连接),它为 IRIS Native 提供了更好的性能。有关更多信息,请参见 First Look:JDBC and InterSystems IRIS(技术概要: JDBC 和 InterSystems IRIS)。3.3 使用 IRIS Native现在,您已经准备好试验 IRIS Native 了。在您已连接的 IDE 中(请参见 “用前须知”),创建一个名为 IRISNative 的新 Java 项目,并粘贴以下代码。确保编辑变量superserverPort(超级服务端口)、username(用户名)、namespace(命名空间)和password(密码),以反映您实例的正确值。import java.sql.DriverManager;import com.intersystems.jdbc.IRISConnection; import com.intersystems.jdbc.IRIS;import com.intersystems.jdbc.IRISIterator; public class IRISNative {protected static int superserverPort = 00000; // YOUR PORT HERE protected static String namespace = "USER"; 探索 IRIS Native protected static String username = "_SYSTEM"; protected static String password = "SYS";public static void main(String[] args) { try {// open connection to InterSystems IRIS instance using connection string IRISConnection conn = (IRISConnection) DriverManager.getConnection("jdbc:IRIS://localhost:"+superserverPort+"/"+namespace,username,password);// create IRIS Native objectIRIS iris = IRIS.createIRIS(conn); System.out.println("[1. Setting and getting a global]");// setting and getting a global// ObjectScript equivalent: set ^testglobal("1") = 8888 iris.set(8888,"^testglobal","1");// ObjectScript equivalent: set globalValue = $get(^testglobal("1")) Integer globalValue = iris.getInteger("^testglobal","1");System.out.println("The value of ^testglobal(1) is " + globalValue); System.out.println(); System.out.println("[2. Iterating over a global]");// modify global to iterate over// ObjectScript equivalent: set ^testglobal("1") = 8888// ObjectScript equivalent: set ^testglobal("2") = 9999 iris.set(8888,"^testglobal","1");iris.set(9999,"^testglobal","2");// iterate over all nodes forwardsIRISIterator subscriptIter = iris.getIRISIterator("^testglobal"); System.out.println("walk forwards");while (subscriptIter.hasNext()) {String subscript = subscriptIter.next(); System.out.println("subscript="+subscript+", value="+subscriptIter.getValue());}System.out.println();System.out.println("[3. Calling a class method]");// calling a class method// ObjectScript equivalent: set returnValue = ##class(%Library.Utility).Date(5) String returnValue = iris.classMethodString("%Library.Utility","Date",5); System.out.println(returnValue);System.out.println();// close connection and IRIS object iris.close();conn.close();} catch (Exception ex) { System.out.println(ex.getMessage());}}} 示例代码分为三个部分:1. 第一部分展示了如何设置一个 global 值以及稍后如何检索它。这部分里面执行的命令等同于 ObjectScript 的 SET 和 GET 命令。2. 第二部分展示了如何迭代 global 的子节点(subnode),类似于 $ORDER ObjectScript 函数。3. 第三部分展示了如何使用 IRIS Native 从您的 Java 应用程序调用 ObjectScript 类方法(class method)。 如果示例执行成功,您应该会看到带有示例代码结果的输出: 了解有关 IRIS Native 的更多信息 [1.Setting and getting a global] The value of ^testglobal(1) is 8888[2.Iterating over a global] walk forwardssubscript=1, value=8888 subscript=2, value=9999[3.Calling a class method] Jan 30, 2018 3.4 确认管理门户(Management Portal)的变更接下来,使用以下程序在管理门户(Management Portal)中确认您的结果。1. 使用 InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中URL described for your instance(为您的实例描述的 URL),在浏览器中打开您实例的管理门户(Management Portal)。2. 如果您不在代码指定的命名空间中,请切换到该命名空间。3. 导航到 Globals 页面(System Explorer(系统资源管理器) > Globals)。您应该会看到在示例代码中创建的 testglobal。点击 View(查看) 来查看其内容。 您应该会看到 global 的两个节点:^testglobal(1) = 8888 和^testglobal(2) = 9999。 4 了解有关 IRIS Native 的更多信息有关 IRIS Native、globals 和 InterSystems IRIS 的更多信息,请参见:First Look:JDBC and InterSystems IRIS(《技术概要:JDBC 和 InterSystems IRIS》)Using Globals(《使用 Globals》)Using the Native API for Java(《使用 Native API for Java》)
文章
Hao Ma · 十一月 2, 2021

IRIS 2021 技术文档 First Look 18 - 在 InterSystems 产品中开发 REST 接口

本文档将向您展示如何开发 REST 接口。您可以将这些 REST 接口与 UI 工具(如 Angular)一起使用,以提供对数据库和互操作性产品的访问。您也可以使用它们支持外部系统访问 InterSystems IRIS®数据平台应用程序。要浏览所有的技术概要(First Look),包括可以在 InterSystems IRIS 免费的评估实例上执行的那些,请参见 InterSystems First Looks(《InterSystems 技术概要》)。 1 为什么提供 REST 接口如果您需要从外部系统访问 InterSystems IRIS 数据库中的数据,或者想为这些数据提供用户界面,您可以通过定义 REST 接口来实现。REST——REpresentational State Transfer——是一种使用公开的 URL 从另一个系统检索、添加、更新或删除数据的方法。REST 基于 HTTP,并使用 HTTP 动词 POST、GET、PUT 和 DELETE 映射到数据库应用程序常见的创建、读取、更新和删除 (CRUD)功能。您还可以在 REST 中使用其他 HTTP 动词,如 HEAD、PATCH 和 OPTIONS。REST 是在应用程序之间共享数据的众多方式之一,因此,如果您选择直接使用其他协议,如 TCP、SOAP 或 FTP 进行通信,则您可能并不总是需要设置 REST 服务。但是使用 REST 有以下优点:• REST 通常只有一个很小的开销(overhead)。它通常使用 JSON,这是一个轻量级的数据包装器。JSON 使用标签标识数据,但标签未在正式模式定义中指定,也没有显式的数据类型。REST 通常比 SOAP 更易于使用,SOAP 使用 XML 且开销(overhead)更大。• 通过在 REST 中定义一个接口,可以很容易地将客户端和数据库服务器之间的依赖关系降到最低。这使您可以在不影响数据库实现的情况下更新用户界面。您还可以在不影响用户界面或访问 REST API 任何外部应用程序的情况下更新数据库实现(database implementation)。 2 对 InterSystems IRIS 的 REST 调用 在定义 REST 接口之前,您应该了解 REST 调用如何流经 InterSystems IRIS。首先,考虑 REST 调用的部分,如:GET http://localhost:52773/rest/coffeemakerapp/coffeemakers 这由以下部分组成:• GET——这是 http 动词。• http:——这指定了通信协议。• //localhost:52773——这指定了托管 REST 接口的 InterSystems IRIS 实例的服务器和端口号。 如何在 InterSystems IRIS 中定义 REST 接口 • /rest/coffeemakerapp/coffeemakers——这是 URL 的主要部分,标识了 REST 调用所指向的资源。在下面的讨论中,URL 指的是 REST 调用的这一部分。 注意: 尽管这个技术概要(First Look)使用安装了 InterSystems IRIS 的 Web 服务器(在本例中是在本地系统的端口 52773 上),但对于部署的任何代码,您都应该使用一个商业 Web 服务器来替换它。安装 InterSystems IRIS 的 web 服务器仅供开发代码时临时使用,并不具备商业 web 服务器的强大功能。 当客户端应用程序进行 REST 调用时:1. InterSystems IRIS 将它指向与 URL 对应的 web 应用程序。例如,以 /coffeemakerapp 开头的 URL 将被发送到处理咖啡机的应用程序,以 /api/docdb 开头的 URL 将被发送到处理文档数据模型(Document Data Model)的 web 应用程序。2. Web 应用程序根据 HTTP 动词(verb)和 URL 中标识 web 应用程序的部分之后的任何部分,将调用指向一个方法。它通过将动词(verb)和 URL 与称为 URLMap 的结构进行比较来实现这一点。3. 该方法使用 URL 来标识 REST 调用所指定的资源,并根据动词(verb)来执行操作。例如,如果动词(verb)是 GET,该方法返回关于资源的一些信息;如果动词(verb)是 POST,该方法创建一个新的资源实例;如果动词(verb)是 DELETE,该方法删除指定资源。对于 POST 和 PUT 动词(verb),通常有一个提供更多信息的数据包。4. 该方法执行所请求的操作,并向客户端应用程序返回一个响应信息。 REST 调用需要执行方法和访问数据所需的任何权限。用户或 web 应用程序都可以拥有这些权限。您可以把这些权限分配给角色,然后把角色分配给用户或 web 应用程序。在这个示例中,%All 角色被分配给 web 应用程序。这允许未知用户(未经身份认证)访问 coffeemakerapp 数据。如果您没有把这个角色分配给 web 应用程序,未知用户将收到 401 未经授权的错误。您必须在 REST 身份认证调用中指定一个有足够权限的用户。详情请参见 "Securing REST Services(《确保 REST 服务》)"。 3 如何在 InterSystems IRIS 中定义 REST 接口在 InterSystems IRIS 中,有两种方法来定义 REST 接口:• 定义 OpenAPI 2.0 规范,然后使用 API 管理(API Management)工具来生成 REST 接口的代码。• 手动编码 REST 接口,然后在管理门户(Management Portal)中定义一个 web 应用程序。 本技术概要(First Look) 展示了如何手动编码 REST 接口,包括开发一个调度类(dispatch class)。如果您更喜欢使用规范优先的方法,这些调度类(dispatch class)是自动生成的,不应该被编辑。使用规范优先定义的优点包括能够从规范自动生成文档和客户端代码,但您可以使用任何一种方式来定义 REST 接口。有关使用规范定义 REST 接口的更多信息,请参见 Creating Rest Services(《创建 REST 服务》)。 4 手动编码 REST 接口 手动编码 REST 接口包括以下步骤:• 创建 %CSP.REST 的子类并定义 UrlMap。 手动编码 REST 接口 • 对处理 REST 调用的方法进行编码。• 定义 web 应用程序——您通常使用管理门户(Management Portal)来执行此操作。 本技术概要(First Look)使用了一个访问咖啡机数据库的示例应用程序 coffeemakerapp 来演示如何手动编码 REST 接口。Coffeemakerapp 提供 REST 接口来获取咖啡机的信息、在数据库中创建新的记录、更新现有的记录或删除记录。以下几节通过注释探讨了此示例应用程序的类定义和一些方法,以增强您对代码的理解。您将在完成本技术概要(First Look) 的练习部分后,从 GitHub 下载整个应用程序的代码。 4.1 创建 %CSP.REST 的子类并定义 URLMap 这是 demo.CoffeeMakerRESTServer 类定义的第一部分。它扩展了 %CSP.REST 类。 Class Demo.CoffeeMakerRESTServer Extends %CSP.REST{Parameter HandleCorsRequest = 1;XData UrlMap [ XMLNamespace = "http://www.intersystems.com/urlmap" ]{<Routes><Route Url="/test" Method="GET" Call="test"/><Route Url="/coffeemakers" Method="GET" Call="GetAll" /><Route Url="/coffeemaker/:id" Method="GET" Call="GetCoffeeMakerInfo" /><Route Url="/newcoffeemaker" Method="POST" Call="NewMaker" /><Route Url="/coffeemaker/:id" Method="PUT" Call="EditMaker" /><Route Url="/coffeemaker/:id" Method="DELETE" Call="RemoveCoffeemaker"/></Routes>} 查看路由(Route)要素。每个都有三个属性:• Url——这标识了可由该路由(Route)处理的 REST URL。由于 IRIS 指向以 /rest/coffeemakerapp 开头的 URL,因此这个属性指定了紧随其后的 URL 部分。如果 Url 属性是 /cof- feemakers,则此路由( Route)处理以 /rest/coffeemakerapp/coffeemakers 开头的 URL。• Method(方法)——这标识了路由(Route)处理的动词。请注意,最后两行的 Url 值相同,/coffeemaker/:id。有 PUT 方法的路由(Route)将处理以 /rest/coffeemaker- app/coffeemaker/:id 开头的 URL 的 PUT 动词,有 DELETE 方法的路由(Route)将处理具有相同开头的 URL 的 DELETE 动词。• Call(调用)——指定要调用的方法来处理这个 REST 调用。该方法会被传递完整的 URL 和任何数据,以便它可以根据 URL 做出响应。 Url 值中以 : 开头的部分表示通配符。也就是说,/coffeemaker/:id 将匹配 /coffeemaker/5,/coffeemaker/200,甚至是 /coffeemaker/XYZ。被调用的方法将在参数中获得 :id 的值。在这种情况下,它标识了要更新(使用 PUT)或删除的咖啡机的 ID。Url 值有额外的选项,允许您将 REST URL 转发到 %CSP.REST 子类的另一个实例,但您不需要在这个技术概要(First Look)中处理它。HandleCorsRequest 参数指定浏览器是否应该允许跨源资源共享(Cross-origin Resource Sharing,CORS),即在一个域中运行的脚本试图访问在另一个域中运行的 REST 服务,但这也是一个高级主题。 4.2 编码方法 GetAll 方法检索有关所有咖啡机的信息。以下是其代码: 手动编码 REST 接口 ClassMethod GetAll() As %Status{Set tArr = []Set rs = ##class(%SQL.Statement).%ExecDirect(,"SELECT * FROM demo.coffeemaker") While rs.%Next() {Do tArr.%Push({"img": (rs.%Get("Img")), "coffeemakerID": (rs.%Get("CoffeemakerID")), "name": (rs.%Get("Name")),"brand": (rs.%Get("Brand")),"color": (rs.%Get("Color")),"numcups": (rs.%Get("NumCups")),"price": (rs.%Get("Price"))})}Write tArr.%ToJSON() Quit $$$OK} 此方法的注意事项:• 没有任何参数。每当这个方法被调用时,它就会执行一个 SQL 语句,从 demo.coffeemaker 数据库中选择所有记录。• 对于数据库中的每条记录,它都会将这些值作为名称、值对附加到数组中。• 它将数组转换为 JSON,并通过将 JSON 编写到 stdout 来将 JSON 返回给调用的应用程序。• 最后,它成功退出。 NewMaker() 方法没有参数,但有一个 JSON 有效负荷,用于指定要创建的咖啡机。以下是其代码:ClassMethod NewMaker() As %Status{If '..GetJSONFromRequest(.obj) {Set %response.Status = ..#HTTP400BADREQUEST Set error = {"errormessage": "JSON not found"} Write error.%ToJSON()Quit $$$OK}If '..ValidateJSON(obj,.error) {Set %response.Status = ..#HTTP400BADREQUEST Write error.%ToJSON()Quit $$$OK}Set cm = ##class(demo.coffeemaker).%New() Do ..CopyToCoffeemakerFromJSON(.cm,obj)Set sc = cm.%Save() Set result={}do result.%Set("Status",$s($$$ISERR(sc):$system.Status.GetOneErrorText(sc),1:"OK")) write result.%ToJSON()Quit sc} 此方法的注意事项:• 首先,它通过调用类中稍后定义的 GetJSONFromRequest() 和 ValidateJSON() 方法,测试有效负荷是否包含有效的 JSON 对象。• 然后它使用 JSON 对象创建一个新的 demo.coffeemaker,将记录保存在数据库中。• 它通过将状态写入 stdout 来返回状态。 最后,RemoveCoffeemaker() 方法展示了 Url 的:id部分是如何作为参数传递给该方法的: 为自己定义 REST 接口 ClassMethod RemoveCoffeemaker(id As %String) As %Status{Set result={}Set sc=0if id'="",##class(demo.coffeemaker).%ExistsId(id) { Set sc=##class(demo.coffeemaker).%DeleteId(id)do result.%Set("Status",$s($$$ISERR(sc):$system.Status.GetOneErrorText(sc),1:"OK"))}else {do result.%Set("Status","")}write result.%ToJSON() quit sc} 总之,由路由调用(Route Call)属性指定的方法通过以下方式处理 REST 调用:• 获得任何参数作为调用参数。• 通过 obj 值访问有效负荷。• 通过将响应写入 stdout,将其返回给客户端应用程序。 5 为自己定义 REST 接口本节逐步向您展示如何使用咖啡机应用程序来处理 REST 调用。与其让您编写 REST 接口的代码,不如从 GitHub 下载完成的应用程序。构建应用程序后,您将定义 Web 应用程序,然后通过 REST 调用测试应用程序。 5.1 用前须知要使用这个程序,您需要在一个系统上工作,安装一个 REST API 应用程序(如 Postman、Chrome 高级 REST 客户端(Chrome Advanced REST Client)或 cURL),并连接一个正在运行的 InterSystems IRIS 实例。您对 InterSystems IRIS 的选择包括多种类型的已授权的和免费的评估实例;该实例不需要由您正在工作的 系统托管(尽管它们必须相互具有网络访问权限)。关于如何部署每种类型的实例的信息(如果您还没有可使用的实例),请参见 InterSystems IRIS Basics: Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中的 Deploying InterSystems IRIS(部署 InterSystems IRIS)。有关将 REST API 应用程序连接到您的 InterSystems IRIS 实例所需的信息,请参见同一文档中的 InterSystems IRIS Connection Information(InterSystems IRIS 连接信息)。 5.2 下载示例应用程序通过克隆或下载已完成的 coffeemakerapp 应用程序来开始这个练习,该应用程序包括测试对 InterSystems IRIS 的 REST 调用所需的所有 REST 接口。这个技术概要-REST(FirstLook-REST)示例代码可以在以下网站获得:https://github.com/intersystems/FirstLook-REST。从 GitHub 下载的内容必须能从您的 InterSystems IRIS 实例访问。下载文件的程序取决于您所使用的实例类型,如下所示:• 如果您使用的是 ICM 部署的实例:1. 使用带有 -machine 和 -interactive 选项的 icm ssh 命令,在托管实例的节点上打开默认 shell,例如:icm ssh -machine MYIRIS-AM-TEST-0004 -interactive 为自己定义 REST 接口 2. 在 Linux 命令行上,使用以下命令之一将 repo 克隆到实例的数据存储卷(data storage volume)。例如,对于部署在 Azure 上的配置,数据卷的默认挂载点(default mount point)是 /dev/sdd,因此您可以使用如下命令: $ git clone https://github.com/intersystems/FirstLook-REST /dev/sdd/FirstLook-REST OR$ wget -qO- https://github.com/intersystems/FirstLook-REST/archive/master.tar.gz | tar xvz -C/dev/sdd 这些文件现在对容器文件系统上 /irissys/data/FirstLook-REST 中的 InterSystems IRIS 可用。 • 如果您正在使用通过其他方式部署的容器化实例(授权版或社区版(Community Edition)):1. 在主机上打开 Linux 命令行。(如果您在云节点上使用社区版(Community Edition),请使用 SSH 连接该节点,如在 Deploy and Explore InterSystems IRIS(《部署和探索 InterSystems IRIS》) 中所述。)2. 在 Linux 命令行上,使用 git clone 或 wget 命令,如上所述,将 repo 克隆到容器中挂载为卷的存储位置。– 对于社区版(Community Edition)实例,您可以克隆到实例的持久化 %SYS 目录 (存储指定于实例的配置数据的目录)。在 Linux 文件系统中,这个目录是 /opt/ISC/dur。这使得文件对容器文件系统上 /ISC/dur/FirstLook-REST 中的 InterSystems IRIS 可用。 – 对于已授权的容器化实例(containerized instance),选择容器中作为卷挂载的任何存储位置(如果使用它,包括持久化 %SYS 目录)。例如, 如果您的 docker run 命令包含选项 -v /home/user1:/external,并且您将 repo 克隆到 /home/user1,则文件对容器文件系统上 /external/FirstLook-REST 中的 InterSystems IRIS 可用。 • 如果您使用的是 InterSystems 学习实验室(Learning Labs)实例:1. 在集成 IDE 中打开命令行终端。2. 将目录更改为 /home/project/shared 并使用 git clone 命令克隆 repo: $ git clone https://github.com/intersystems/FirstLook-REST 该文件夹被添加到左边资源管理器(Explorer)面板的 Shared (共享)下,并且该目录对 /home/project/shared 中的 InterSystems IRIS 可用。• 如果您使用的是已安装的实例:– 如果实例的主机是安装了 GitHub 桌面(GitHub Desktop)和 GitHub 大文件存储(GitHub Large File Storage)的 Windows 系统:1. 在主机的 web 浏览器中进入 https://github.com/intersystems/FirstLook-REST。2. 选择 Clone or download(克隆或下载) 然后选择 Open in Desktop(在桌面上打开)。 这些文件对您的 GitHub 目录中的 InterSystems IRIS 可用,例如在 C:\Users\User1\Documents\GitHub\FirstLook-REST 中。– 如果主机是 Linux 系统,只需在 Linux 命令行上使用 git clone 命令或 wget 命令,就可以将 repo 克隆到您所选择的位置。 5.3 创建一个支持互操作性的命名空间如果您已经有了一个互操作性命名空间,就可以使用它。否则,创建一个命名空间:1. 使用 InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中为您的实例描述的 URL,在浏览器中打开您的实例的管理门户(Management Portal)。 为自己定义 REST 接口 2. 通过导航到命名空间(Namespaces)页面(System Administration(系统管理) > Configuration(配置) > System Configuration(系统配置) > Namespaces(命名空间)), 并按照 System Administration Guide(《系统管理指南》)的“Configuring InterSystems IRIS(《配置 InterSystems IRIS》)”一章中创建/修改命名空间中的使用新命名空间(New Namespace)页面的说明,点击 Create New Namespace(创建新命名空间)按钮,创建一个支持互操作性的命名空间。 5.4 构建示例代码 要构建示例代码,请按照以下步骤操作1. 使用 InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中为您的实例描述的程序,打开 InterSystems 终端(Terminal)。2. 将命名空间设置为您将使用的互操作性命名空间。输入以下命令,替换 <Namespace-name> 与您所使用的命名空间。set $namespace = "<namespace-name>" 3. 输入以下命令,替换 <path> 与您下载示例的路径。 该目录包含许可证(License)和 Readme 文件以及 buildsample 目录:do $system.OBJ.Load("<path>/buildsample/Build.RESTSample.cls","ck") do ##class(Build.RESTSample).Build()4. 当出现提示时,输入下载此示例的目录的完整路径。然后,该方法加载和编译代码,并执行其他需要的设置步骤。注意: FirstLook-REST / README.md 文件包含这些说明的一个版本。5.5 定义一个 web 应用程序 现在您已经使用 REST 接口构建了示例应用程序,您需要定义一个 web 应用程序:1. 使用 InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中为您的实例描述的 URL,在浏览器中打开您的实例的管理门户(Management Portal)。2. 选择 System Administration(系统管理) > Security(安全) > Applications(应用程序) > Web Applications(web 应用程序)。3. 选择 Create New Web Application(创建新的 web 应用程序) 并输入以下设置• Name(名称): /Rest/coffeemakerapp——它指定了将由这个 web 应用程序处理的 URL。InterSystems IRIS 会将所有以 /rest/coffeemakerapp 开头的 URL 定向到这个 web 应用程序。• Namespace(命名空间): 您创建的支持互操作性的名称空间的名称。• Enable(支持): 选择 REST。• Dispatch Class(调度类): Demo.CoffeeMakerRESTServer——这是定义了 URLMap 的类。• Security Settings/Allowed Authentication Methods(安全设置/允许的身份认证方法): 同时选择 Unauthenticated(未经身份认证) 和 Password(密码) 复选框。4. 选择 Save(保存)。5. 要允许此示例的未经身份认证的访问,必须赋予 web 应用程序 %All 角色。要执行此操作:a. 选择 Save(保存)后,选择 Application Roles(应用程序角色)标签。b. 从 Available(可用的)角色中选择 %All 角色。c. 点击右箭头(选择)按钮,将 %All 角色移动到 Selected(选定的) 角色。 为自己定义 REST 接口 d. 点击 Assign(分配) 按钮。e. %All 角色现在被列为 Application Role(应用程序角色)。这确保了来自未经身份认证用户的 REST 调用将拥有访问 coffeemakerapp 数据所需的权限。如果没有这个角色,REST 调用将必须为拥有足够权限的用户指定身份认证。 5.6 访问 REST 接口 CoffeeMaker REST 应用程序现在可以工作了。您将输入 REST 命令来访问咖啡机数据库。在您的 REST API 工具(如 Postman)中,按照以下步骤操作:1. 指定 REST POST 请求来添加新的咖啡机,必要时使用您的 InterSystems IRIS 实例的指定信息• HTTP 操作: POST• URL: http://server:port/rest/coffeemakerapp/newcoffeemaker,其中服务器和端口是您的实例的主机标识符和 web 服务器端口。• 您的实例的登录凭证。• 输入数据: {"img":"img/coffee3.png","coffeemakerID":"99","name":"Double Dip","brand":"Coffee+", "color":"Blue","numcups":2,"price":71.73} 尽管数据包含一个 coffeemakerID 的值,但这是一个计算字段,并且在添加记录时会分配一个新值。该调用返回成功状态:{"Status":"OK"} 2. 重复上一步骤两次,添加以下两个咖啡机: {"img":"img/coffee4.png","coffeemakerID":"99","name":"French Press","brand":"Coffee For You", "color":"Blue","numcups":4,"price":50.00}{"img":"img/coffee9.png","coffeemakerID":"99","name":"XPress","brand":"Shiny Appliances", "color":"Green","numcups":1,"price":95.00} 3. 使用相同的实例指定信息,指定一个 REST GET 请求,以获得数据库中的咖啡机列表:• HTTP 操作: GET• URL: http://server:port/rest/coffeemakerapp/coffeemakers• 您的实例的登录凭证。 该调用返回一个咖啡机列表,如: [{"img":"img/coffee3.png","coffeemakerID":"1","name":"Double Dip","brand":"Coffee+", "color":"Blue","numcups":2,"price":71.73},{"img":"img/coffee4.png","coffeemakerID":"2","name":"French Press","brand":"Coffee For You", "color":"Blue","numcups":4,"price":50},{"img":"img/coffee9.png","coffeemakerID":"3","name":"XPress","brand":"shiny Appliances", "color":"Green","numcups":1,"price":95}] 4. 指定以下 REST 调用,删除 ID=2 的咖啡机:• HTTP 操作:DELETE• URL: http://server:port/rest/coffeemakerapp/coffeemaker/2• 您的实例的登录凭证。 为自己定义 REST 接口 该调用返回成功状态: {"Status":"OK"} 5. 重复 REST GET 请求。该调用返回一个咖啡机列表,如: [{"img":"img/coffee3.png","coffeemakerID":"1","name":"Double Dip","brand":"Coffee+", "color":"Blue","numcups":2,"price":71.73},{"img":"img/coffee9.png","coffeemakerID":"3","name":"XPress","brand":"Shiny Appliances", "color":"Green","numcups":1,"price":95}] 5.7 记录 REST 接口 当您向开发者提供 REST 接口时,您应该提供文档,以便他们知道如何调用接口。您可以使用 Open API Spec 来记录 REST 接口,并使用工具,如 Swagger 来编辑和格式化文档。InterSystems 正在开发一项功能来支持这个文档。这个版本包含了 API 管理(API Management)中的一个功能,它可以为您的 REST API 生成文档框架。您仍然需要编辑生成的文档,以添加注释和额外的信息,例如参数和 HTTP 返回值的内容。要为 CoffeeMakerApp REST 示例生成文档,请输入以下 REST 调用,使用您的 InterSystems IRIS 实例的指定信息和您创建的命名空间的名称:• HTTP 操作:GET• URL: http://server:port/api/mgmnt/v1/namespace/spec/rest/coffeemakerapp/• 您的 InterSystems IRIS 实例的登录凭证。 您可以把这个调用的输出粘贴到 swagger 编辑器中。它将 JSON 转换为 YAML(另一种标记语言(Yet Another Markup Language))并显示文档。您可以使用 swagger 编辑器向文档中添加更多信息。Swagger 编辑器显示的文档如下所示: 有关 InterSystems IRIS 和 REST 的更多信息 6 有关 InterSystems IRIS 和 REST 的更多信息 有关在 InterSystems IRIS 中创建 REST 服务的更多信息,请参见以下内容:• Setting Up RESTful Services(设置 RESTful 服务) 是 InterSystems 的在线课程,它使用与本文档相同的咖啡机应用程序,但更详细。 您需要登录 learning.intersystems.com 才能参加这个课程。如果您没有账户,可以创建一个。• Creating REST Services(《创建 REST 服务》)• Using REST Services and Operations in Productions(《在产品中使用 REST 服务和操作》)
文章
jieliang liu · 十月 26, 2021

IRIS 2021 技术文档 First Look 29 技术概要:LDAP 和 InterSystems 产品

技术概要:LDAP 和 InterSystems 产品 目录 技术概要: LDAP 和 InterSystems 产品 1 设置 LDAP 身份验证 1 选择 InterSystems IRIS 实例 1 定义 LDAP 配置 1 选择新的 LDAP 域作为默认值 2 启用 LDAP 身份验证 2 为 LDAP 服务器安装安全证书 3 探索 LDAP 用户和组 4 User1: 操作员 4 User2: 管理者 5 User3: 开发者 5 自动创建用户 6 了解有关 LDAP 和安全的更多信息 6 技术概要:LDAP 和 InterSystems 产品 InterSystems IRIS®数据平台可以与 LDAP(轻量级目录访问协议,Lightweight Directory Access Protocol)服务器集成,从而可以无缝地使用这种流行技术对用户进行身份验证。通过 LDAP 提供授权也很容易。 当用户尝试登录 InterSystems IRIS 时,用户名和密码会被发送到 LDAP 服务器,以验证该用户是否存在。一旦用户的身份得到验证,LDAP 服务器就会向 InterSystems IRIS 发送关于用户属于哪些组的信息。这些组与 InterSystems IRIS 中的角色相对应,这些角色控制用户被授权执行什么操作,以及是否可以读取或写入内容。通过这种方式,InterSystems IRIS 在其安全策略的身份验证和授权方面都使用了 LDAP 技术。 按照本指南中的步骤,您可以连接到 LDAP 服务器,并探索它如何影响 InterSystems IRIS 中的安全。在这些练习中,您将配置 InterSystems IRIS 以与 Windows 活动目录(Active Directory)服务器集成。虽然也支持其他的 LDAP 服务器,但本文主要介绍如何使用活动目录(Active Directory)进行 LDAP 身份验证和授权。 要浏览所有的技术概要(First Look),包括下面描述的可以在免费的社区版(Community Edition)实例上执行的其他内容,请参见 InterSystems First Looks(《InterSystems 技术概要》)。 设置 LDAP 身份验证 在以 LDAP 用户登录并在 InterSystems IRIS 中探索基于 LDAP 的安全之前,需要完成以下操作: 选择 InterSystems IRIS 实例 定义 LDAP 配置 选择 LDAP 域作为默认值 在 InterSystems IRIS 中启用 LDAP 身份验证 为 LDAP 服务器安装安全证书 选择 InterSystems IRIS 实例 要使用该程序,您需要一个正在运行的 InterSystems IRIS 实例。您的选择包括多种类型的已授权的和免费的评估实例;该实例不需要由您正在工作的系统托管(尽管它们必须相互具有网络访问权限)。关于如何部署每种类型的实例的信息(如果您还没有可使用的实例),请参见 InterSystems IRIS Basics: Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中的 Deploying InterSystems IRIS(部署 InterSystems IRIS)。 定义 LDAP 配置 InterSystems IRIS 使用 LDAP 配置来定义连接到 LDAP 服务器和搜索用户所需的信息。要创建和定义新的 LDAP 配置: 设置 LDAP 身份验证 在浏览器中打开您的实例的管理门户(Management Portal)。要使用的 URL 取决于您选择的实例类型;有关确定正确的 URL 的信息,请参见 InterSystems IRIS Basics:Connecting an IDE(《InterSystems IRIS 基础:连接一个 IDE》)中的 InterSystems IRIS Connection Information(InterSystems IRIS 连接信息)。 进入 Security LDAP Configurations(安全 LDAP 配置) 页面 (System Administration(系统管理) > Security(安全) > System Security(系统安全) > LDAP Configurations(LDAP 配置))。 点击 Create New LDAP configuration(创建新 LDAP 配置)。 在 Name(名称)字段中,输入 irisldap.com。 选择 Enabled(已启用) 复选框。 选择 LDAP server is a Windows Active Directory server(LDAP 服务器是一个 Windows 活动目录(Active Directory) 服务器) 复选框。 定义以下字段: +-----------------------------------------------------------------+---------------------------------------------------------------------------+ | 字段 | > 内容 | +=================================================================+===========================================================================+ | LDAP domain name(LDAP 域名) (仅限 Windows) | > irisldap.intersystems.com | +-----------------------------------------------------------------+---------------------------------------------------------------------------+ | LDAP host names(LDAP 主机名) | > irisldapdc1.irisldap.intersystems.com | +-----------------------------------------------------------------+---------------------------------------------------------------------------+ | LDAP username to use for searches(用于搜索的 LDAP 用户名) | - (Windows) sidLDAPQuery | | | | | | - (UNIX®) | | | | | | > CN=sidLDAPQuery,CN=Users,DC=irisldap,DC=intersystems,DC=com | +-----------------------------------------------------------------+---------------------------------------------------------------------------+ | LDAP username password(LDAP 用户名密码) | > 选择 Enter New Password(输入新密码), 然后输入密码为 Cach3L3arning | +-----------------------------------------------------------------+---------------------------------------------------------------------------+ | LDAP Base DN to use for searches(用于搜索的 LDAP 基础 DN) | > DC=irisldap,DC=intersystems,DC=com | +-----------------------------------------------------------------+---------------------------------------------------------------------------+ | LDAP Unique search attribute(LDAP 独特的搜索属性) | > sAMAccountName | +-----------------------------------------------------------------+---------------------------------------------------------------------------+ 选择 Use TLS/SSL encryption for LDAP sessions(将 TLS/SSL 加密用于 LDAP 会话)复选框。 选择 Use LDAP Groups for Roles/Routine/Namespace(将 LDAP 组用于角色/路由/命名空间)复选框。 选择 Allow Universal group Authorization(允许通用组授权)复选框。 点击 Save(保存)。 选择新的 LDAP 域作为默认值 一旦定义了 LDAP 服务器的 LDAP 配置,您需要将新的 LDAP 配置设置为默认的 LDAP 域。要将 LDAP 服务器设置为默认服务器: 从管理门户(Management Portal)主页,进入 System-wide Security Parameters(全系统安全参数) 页面 (System Administration(系统管理) >**Security(安全) > System Security(系统安全) > System-wide Security Parameters(全系统安全参数)**)。 从 Default security domain(默认安全域)下拉列表中选择 irisldap.com。 点击 Save(保存)。 启用 LDAP 身份验证 使用 LDAP 服务器只是 InterSystems IRIS 中可用的一种身份验证方法。不仅必须为 InterSystems IRIS 的整个实例启用 LDAP 身份验证,而且需要由 LDAP 用户访问的 InterSystems IRIS 的每个组件也必须启用 LDAP 身份验证。以下程序为实例和 InterSystems IRIS 安全所需的那些组件启用 LDAP 身份验证: 设置 LDAP 身份验证 从管理门户(Management Portal)主页,进入 Authentication/Web Session Options(身份验证/Web 会话选项) 页面(System Administration(系统管理)> Security(安全) > System Security(系统安全) > Authentication/Web Session Options(身份验证/Web 会话选项))。 选择 Allow LDAP authentication(允许 LDAP 身份验证)复选框。 点击 Save(保存)。 从管理门户(Management Portal)主页,进入 Web Applications(Web 应用程序)页面 (System Administration(系统管理) > Security(安全) > Applications(应用程序) > Web Applications(Web 应用程序))。 在这个页面上,您将为您在 InterSystems IRIS 中将要访问的管理门户(Management Portal)部分启用 LDAP 授权。因为管理门户(Management Portal)的其他部分没有启用 LDAP 授权,如果您试图探索这些其他部分,可能会被要求登录。 点击 /csp/sys 来显示用于配置 web 应用程序的页面。 在 Security Settings(安全设置) 部分,在 Allowed Authentication Methods(允许的身份验证方法)字段中选择 LDAP 复选框。 点击 Save(保存)。 一旦设置被保存,点击 Cancel(取消)以返回到 Web Applications(Web 应用程序)页面。 点击 /csp/sys/sec。这个 web 应用程序包含管理门户(Management Portal)的安全页面。 在 Security Settings(安全设置)部分,在 Allowed Authentication Methods(允许的身份验证方法)字段中选择 LDAP 复选框。 点击 Save(保存)。 一旦设置被保存,点击 Cancel(取消)以返回到 Web Applications(Web 应用程序) 页面。 点击 /csp/sys/op。这个 web 应用程序包含管理门户(Management Portal)的操作页面。 <span id="1.5_Installing_a_Security_Certificate_fo" class="anchor"></span>在 Security Settings(安全设置) 部分,在 Allowed Authentication Methods(允许的身份验证方法)字段中选择 LDAP 复选框。 点击 Save(保存)。 为 LDAP 服务器安装安全证书 LDAP 服务器采用 TLS 进行安全保护,因此您需要安装安全证书才能成功访问服务器。在将其标识为安全证书之前,您将创建一个包含所需证书内容的 .cer 文件。 创建 .cer 文件 要创建将作为安全证书安装的文件: 打开一个文本编辑器,如记事本,并创建一个新文件。 复制以下所有内容并将其粘贴到文本编辑器中的新文件中。新文件应该以 -----BEGIN CERTIFICATE-----开头,并以-----END CERTIFICATE-----结尾。 -----BEGIN CERTIFICATE----- MIIDuTCCAqGgAwIBAgIQO5hG2uC7G7ZBxcXt/J+z3TANBgkqhkiG9w0BAQsFADBv MRMwEQYKCZImiZPyLGQBGRYDY29tMRwwGgYKCZImiZPyLGQBGRYMaW50ZXJzeXN0 ZW1zMRgwFgYKCZImiZPyLGQBGRYIaXJpc2xkYXAxIDAeBgNVBAMTF2lyaXNsZGFw LUlSSVNMREFQREMxLUNBMB4XDTE4MDQwOTE0MDUzMloXDTIzMDQwOTE0MTUzMlow bzETMBEGCgmSJomT8ixkARkWA2NvbTEcMBoGCgmSJomT8ixkARkWDGludGVyc3lz dGVtczEYMBYGCgmSJomT8ixkARkWCGlyaXNsZGFwMSAwHgYDVQQDExdpcmlzbGRh cC1JUklTTERBUERDMS1DQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB AL/aNDJJNbzGh6tXG8+hmEEplb80UQMcIhLvoanz/RKKZXBBY68rO5pkYUwn/24g pryGy0OUjA997KKol5rdbXWzK7vUMuVSp0atw1m4vF9hmp1bpKBC60OXmV39Fqar ej1dkRl0ZXOmCexP8JqTyNwhpOLXvazzzvsNRr4ts9u1m6y9kFYecu4PRqtFCgoC T6rbgqz1Ew3VrhQHi0HWvq1sR2CngxdyG8AnlSo6nz3X/IrTwrw5lauNLfpsRda5 D5YfUpxYeqpONSUB650u9bC0l5eRWe8kS33Xr+u5Odkhy087I/zN+GK7xMGzxYMR OWNINIGRvlLuDRshKQl4gP0CAwEAAaNRME8wCwYDVR0PBAQDAgGGMA8GA1UdEwEB /wQFMAMBAf8wHQYDVR0OBBYEFM3Ofv4R/zkEgHkp4ayvTkAvxJikMBAGCSsGAQQB gjcVAQQDAgEAMA0GCSqGSIb3DQEBCwUAA4IBAQC8hhvc/+WsDeipNezBo+ovum2z 7q0fStr73Tj84cDGSyCmT2Q/h0qFvkfjtRd8AUBdG0qjhIB4VLVyWmrWDl1jAUcr 3AzygfO6UZjNRT+4c8r8R2xOhE3wJEJWibzXD9bPCtCkhYNJT6bi5PSRgUq+r9GU 探索 LDAP 用户和组 IHnAUmaQa+K+kNEpAvBfIeQ2ox9NPbtUfj/fswKpubWzZZc2udeU8SQLacl6tZMA tXgZPT6lQfoZU2WmDG1EnoC4Ji1++Sf6Ho2i6kxg1m6geyOPSsGPdsAVjYCqCjuZ pxjAsfZXV2juLyTBM51rrmV/Rqfougnikh4zhFRBrOHtMP71ZxCptMVz3RHe -----END CERTIFICATE----- 在您可以访问的目录中将该文件另存为 irisldap.cer。 在 Windows 上安装安全证书 如果您在 Windows 上运行 InterSystems IRIS,请完成以下步骤来完成安装您所创建的安全证书的过程。 使用 Windows 资源管理器(Explorer),双击在您保存文件的目录中的安全文件 irisldap.cer。 点击 Install Certificate(安装证书)。 选择 Local Machine(本地机器) 并点击 Next(下一步)。 点击 Yes(是) 以允许对您的设备进行更改。 选择 Place all certificates in the following store(将所有证书放入以下存储区)并点击 Browse(浏览)。 选择 Trusted Root Certification Authorities(受信任的根证书颁发机构)并点击 OK(确定)。 点击 Next(下一步)。 点击 Finish(完成)。 在 UNIX®上安装安全证书 如果您在 UNIX®上运行 InterSystems IRIS,请完成以下步骤来完成安装您所创建的安全证书的过程。 以 _system 用户身份登录管理门户(Management Portal)时,进入 Security LDAP Configurations(安全 LDAP 配置) 页面 (System Administration(系统管理) > Security(安全) > System Security(系统安全) > LDAP Configurations(LDAP 配置))。 从 LDAP 配置的列表中点击 irisldap.com。 在 TLS/SSL certificate file(TLS/SSL 证书文件)字段中,输入 irisldap.cer 的路径和文件名,这是您创建并保存的文件。 探索 LDAP 用户和组 现在您已经配置了您的 LDAP 连接并启用了 LDAP 身份验证,您可以使用 LDAP 服务器来登录 InterSystems IRIS。LDAP 服务器包含三个用户:user1、user2 和 user3。user1 属于 intersystems-Role-%Operator 组,user2 属于 intersystems-Role-%Manager 组,user3 属于 intersystems-Role-%Developer 组。每个组都授予属于 InterSystems IRIS 中相应角色的权限。例如,当 user1 通过 LDAP 服务器的身份验证成功时,将为其分配 %Operator 角色。 在本教程中,您将以所有三个用户的身份登录到 InterSystems IRIS,并根据与用户关联的角色探索可用的操作。当您作为一个有效的 LDAP 用户登录到 InterSystems IRIS 时,InterSystems IRIS 会自动创建用户,而不需要您事先手动添加用户。 User1: 操作员 要以 user1 的身份登录并探索 InterSystems IRIS: 如果您目前已登录到 InterSystems IRIS,请点击管理门户(Management Portal)左上角的 Logout(退出) 链接。 探索 LDAP 用户和组 使用以下凭证登录 InterSystems IRIS: 用户名:user1 密码:Password1 user1 是 intersystems-Role-%Operator 组的成员。基于这个组,当 user1 通过身份验证时,他们会被自动授予与 InterSystems IRIS 中 %Operator 角色相关的权限。 从管理门户(Management Portal)主页,进入 Databases(数据库) 页面 (System Operation(系统操作) > Databases(数据库))。user1 可以访问这个页面,因为他们已经被 LDAP 服务器授权,可以和与 %Operator 角色关联的页面进行交互。 在管理门户(Management Portal)主页上,请注意 System Administration(系统管理) 菜单已被禁用。 user1 不能访问此菜单,因为 %Operator 角色不包含适当的权限。 User2: 管理者 要以 user2 的身份登录并探索 InterSystems IRIS: 点击管理门户(Management Portal)左上角的 Logout(退出) 链接。 使用以下凭证登录 InterSystems IRIS: 用户名:user2 密码:Password2 user2 是 intersystems-Role-%Manager 组的成员。基于这个组,当 user2 通过身份验证时,他们会被自动授予与 %Manager 角色相关的权限。正如您将看到的,这些权限包括访问 user1 无法看到的页面。 从管理门户(Management Portal)主页,进入 Users(用户) 页面 (System Administration(系统管理) > Security(安全) > Users(用户))。请记住,user1 不能访问 System Administration(系统管理) 菜单。 从用户列表中点击 user1。 点击 Roles(角色) 标签。 请注意,%Operator 是分配给 user1 的唯一角色。 点击 Cancel(取消) 以返回到 Users(用户) 页面。 请注意,在用户列表中没有 user3 的条目。该用户将在 user3 登录时自动创建,此时 InterSystems IRIS 使用 LDAP 服务器对用户进行身份验证。 User3: 开发者 要以 user3 的身份登录并探索 InterSystems IRIS: 点击管理门户(Management Portal)左上角的 Logout(退出)链接。 使用以下凭证登录 InterSystems IRIS: 用户名:user3 密码:Password3 user3 是 intersystems-Role-%Developer 组的成员。基于这个组,当 user3 通过身份验证时,他们会被自动授予与 %Developer 角色相关的权限。 请注意,该用户可以访问 System Explorer(系统资源管理器)菜单,而不是 System Operation(系统操作)和 System Administration(系统管理)菜单。您可以看出,分配给 user3 的 %Developer 角色与分配给 了解有关 LDAP 和安全的更多信息 user1 和 user2 的角色具有不同的权限。这可以防止 user3 看到自己的用户配置文件,因为 Users(用户)页面是在 System Administration(系统管理)菜单下。 自动创建用户 您已经登录到 InterSystems IRIS,但没有先创建新用户。当在 LDAP 服务器上发现这些用户时,InterSystems IRIS 会自动创建这些用户。下面的程序演示了这个过程: 点击管理门户(Management Portal)左上角的 Logout(退出)链接。 使用以下凭证登录 InterSystems IRIS: 用户名:user2 密码:Password2 请记住,user2 拥有 %Manager 角色。 从管理门户(Management Portal)主页,进入 Users(用户) 页面 (System Administration(系统管理) > Security(安全) > Users(用户))。 在列表中找到 user3 并点击行中的 Delete(删除)。 此时,拥有 %Developer 角色的 user3 在 InterSystems IRIS 中不复存在。 点击管理门户(Management Portal)左上角的 Logout(退出)链接。 使用以下凭证登录 InterSystems IRIS: 用户名:user3 密码:Password3 因为 user3 仍然存在于 LDAP 服务器上,所以即使您刚刚在 InterSystems IRIS 中删除了用户帐户,您也能够以 user3 的身份重新登录到 InterSystems IRIS。 如果需要,您可以重新登录 InterSystems IRIS,以确认 user3 现在是一个用户。 a. 点击管理门户(Management Portal)左上角的 Logout(退出)链接。 b. 使用以下凭证登录 InterSystems IRIS: 用户名:user2 密码:Password2 c. 从管理门户(Management Portal)主页,进入 System Administration(系统管理) > Security(安全) > Users(用户)。user3 现在在列表中,尽管您之前删除了该用户账户。 了解有关 LDAP 和安全的更多信息 您可以使用以下参考资料来了解有关 LDAP 和其他安全概念的更多信息。 有关在 InterSystems IRIS 中使用 LDAP 的详细信息,请参见 LDAP Guide(《LDAP 指南》)。 有关 InterSystems IRIS 中基于角色的安全的介绍,请参见 First Look:Role-Based Access Control(《技术概要:基于角色的访问控制》)。
文章
姚 鑫 · 一月 19, 2023

第五十章 使用 ^SystemPerformance 监视性能 - Microsoft Windows 平台的 InterSystems IRIS 性能数据报告

# 第五十章 使用 ^SystemPerformance 监视性能 - Microsoft Windows 平台的 InterSystems IRIS 性能数据报告 #### Microsoft Windows 平台的 IRIS 性能数据报告 - `%SS` - 使用 `ALL^%SS` 命令在运行过程中采集了四个样本。 - `Configuration *` - 来自服务器的 `IRIS` 实例名称和主机名、完整的 `IRIS` 版本字符串、许可客户名称和许可订单号。 - `cpf file *` - 当前活动配置文件的副本。 - `irisstat -c` - 使用命令 `.\bin\irisstat -s -p-1 -c-1 -e1 -m8 -n2 -N127` 在运行过程中以均匀间隔采集四个样本。以下是对每个参数的简要说明: - `-p-1`: 对进程表进行采样以包括进程和全局状态信息。 - `-c-1`: 对共享内存的计数器部分进行采样以显示日志、锁、磁盘和资源使用统计信息。 - `-e1`: `SYSLOG` 错误表。 - `-m8`: 文件表,其中包括所有 `IRIS.DAT` 文件及其属性。 - `-n2`: 网络结构表,包括本地到远程数据库的映射。 - `-N127`: 客户端和服务器连接的 `ECP` 统计信息。 - `irisstat -D` - 使用命令 `irisstat cache --f1 -D10,100` 在运行过程中以均匀的间隔采集八个样本。以下是对每个参数的简要说明: - `-fl`: 基本标志。 - `-D10,100`: 在 `10` 秒的总采样周期内,每 `100` 毫秒对块碰撞进行采样。 - `license *` - 使用 `Decode^%LICENSE` 和 `counts^%LICENSE` 的 `IRIS` 许可使用信息。 - `mgstat` - 使用 `^mgstat` 实用程序在运行过程中获取 `IRIS` 特定数据。 - `perfmon` - `Microsoft Windows perfmon` 实用程序的输出。 `Microsoft Windows perfmon` 数据的默认呈现方式是原始格式。可以将格式切换为已处理,这会删除重复的服务器名称并将日期时间列拆分为单独的列,以提高可读性。以下函数允许查询和更新确定 `perfmon` 数据是否被操作的标志:`set rc=$$setperfmonpostproc^SystemPerformance(`) 其中 `onoroff` 可以是 `1`(开)或 `0`(关),或者不区分大小写的单词`“on”`或`“off”`。返回码 `1` 表示标志更新成功,`0` 表示更新失败,`-1` 表示非 `Windows` 平台。要确定当前格式(原始格式或已处理格式):`set status=$$getperfmonpostproc^SystemPerformance()` 返回代码 `1` 表示已处理格式,`0` 表示原始格式。此外,在 `^SystemPerformance` 的交互式运行中,在配置文件菜单显示之前报告标志的当前状态。默认情况下,`perfmon` 监视默认 `pbctrs.txt` 文件中指定的计数器定义。要监视先前定义的性能计数器,请使用以下命令将定义导入 `^SystemPerformance`:写入 `$$importctrs^SystemPerformance(WindowsCtrName [,SystemPerformanceCtrName [,SystemPerformanceFileName]])` 返回代码 `0` 表示成功,负数后跟原因字符串表示失败.不允许重复的 `SystemPerformance` 计数器名称。如有必要,`^SystemPerformance` 会生成内部计数器名称和文件名。要将默认的 `SystemPerformance` 计数器定义更改为现有定义,请使用:`write $$setctrddefault(SystemPerformanceCtrName)` 返回代码 `1` 表示成功,后跟原因字符串的 `0` 表示失败。如果指定了无效计数器,则会设置内置默认值。要重置默认的 `SystemPerformance` 计数器定义,请使用:`do clrctrdefault^SystemPerformance()` 要将特定的 `SystemPerformance` 计数器定义与现有配置文件相关联,请使用:`write $$addctrtoprofile(ProfileName,SystemPerformanceCtrName)` 返回码 `1` 表示成功,`0` 后跟一个原因字符串表示失败。如果配置文件或计数器定义不存在,则不会运行该命令。 - `Profile *` - 有关创建此日志的 `^SystemPerformance` 配置文件的信息。 - `tasklist` - `tasklist -V` 命令的四个输出,在运行过程中以均匀的间隔获取。 `tasklist -V` 命令提供系统上运行的所有进程的列表。 - `Windows info *` - `systeminfo` 命令的输出,包括 `Windows` 版本(不包括修补程序信息)和硬件信息;例如,处理器数量、安装的内存和使用的内存。
文章
姚 鑫 · 一月 21, 2023

第五十二章 使用 ^SystemPerformance 监视性能 - IBM AIX® 平台的 InterSystems IRIS 性能数据报告

# 第五十二章 使用 ^SystemPerformance 监视性能 - IBM AIX® 平台的 InterSystems IRIS 性能数据报告 - `%SS` - 使用 `ALL^%SS` 命令在运行过程中采集了四个样本。 - `AIX info *` - `oslevel` 的输出。 `uname -a`、`prtconf` 和 `lspv `命令 - `Configuration *` - 来自服务器的 `IRIS` 实例名称和主机名、完整的 `IRIS` 版本字符串、许可客户名称和许可订单号。 - `cpf file *` - 当前活动配置文件的副本。 - `cpu type *` - 有关安装的处理器以及是否启用 `SMT` 的信息; `lsattr -El proc0` 的输出。 - `irisstat -c` - 使用命令 `irisstat cache -p-1 -c-1 -e1 -m8 -n2 -N127` 在运行过程中以均匀的间隔采集四个样本。以下是对每个参数的简要说明: - `-p-1`: 对进程表进行采样以包括进程和全局状态信息。 - `-c-1`: 对共享内存的计数器部分进行采样以显示日志、锁、磁盘和资源使用统计信息。 - `-e1`: `SYSLOG` 错误表。 - `-m8`: 文件表,其中包括所有 `IRIS.DAT` 文件及其属性。 - `-n2`: 网络结构表,包括本地到远程数据库的映射。 - `-N127`: 客户端和服务器连接的 `ECP` 统计信息。 - `irisstat -D` - 使用命令 `irisstat cache --f1 -D10,100` 在运行过程中以均匀的间隔采集八个样本。以下是对每个参数的简要说明: - `-fl`: 基本标志。 - -`D10,100`: 在 `10` 秒的总采样周期内,每 `100` 毫秒对块碰撞进行采样。 - `df -k *` - 有关挂载文件系统的信息,包括挂载点、逻辑卷和可用空间; `df -k` 命令的输出。 - `filesystems *` - 当前 `/etc/filesystems` 文件。 - `ioo -a *` - `I/O`可调参数的当前值; `ioo -a` 命令的输出。仅当启动 `^SystemPerformance` 配置文件运行的用户具有 `root` 访问权限时才包括在内。 - `iostat -DIT` - 带有 `IBM AIX® 5.3` 及更新版本采样时间的扩展磁盘/设备统计信息的长列表; `iostat -DIT` 命令的输出。信息因 `IBM AIX® 5.3` 之前的发行版而异。 - `ipcs *` - 进程间通信配置信息,包括共享内存、信号量和消息队列; `ipcs -a` 命令的输出。 - `license *` - 使用 `Decode^%LICENSE` 和 `counts^%LICENSE` 的 `IRIS` 许可使用信息。 - `mount *` - 有关所有文件系统及其挂载选项的信息。 - `mgstat` - 使用 `^mgstat` 实用程序在运行过程中获取 `IRIS` 特定数据。请参阅 `Monitoring Guide` 的 `Monitoring Performance Using ^mgstat` 部分。 - `Profile *` - 有关创建此日志的 `^SystemPerformance` 配置文件的信息。 - `ps:` - 使用命令 `ps aux` 在运行过程中以均匀的间隔采集四个样本。 - `sar -d` - 仅当启动 `^SystemPerformance` 配置文件运行的用户具有 `root` 访问权限并且 `/usr/sbin/sar` 存在时才包括在内。 - `sar -r` - 仅当启动 `^SystemPerformance` 配置文件运行的用户具有 `root` 访问权限并且 `/usr/sbin/sar` 存在时才包括在内。 - `sar -u` - 包括微分区信息(如果使用)的 `CPU` 统计信息。仅当启动 `^SystemPerformance` 配置文件运行的用户具有 `root` 访问权限并且 `/usr/sbin/sar` 存在时才包括在内。 - `vmo –a` - 虚拟内存可调参数的当前值; `vmo -a` 命令的输出。仅当启动 `^SystemPerformance` 配置文件运行的用户具有 `root` 访问权限时才包括在内。 - `vmstat -s *` - 虚拟内存统计的绝对计数,包括总页入和页出。 - `vmstat -t` - 带有时间戳的虚拟内存和 `CPU`(分页、排队和 CPU)统计信息。 - `vmstat -v *` - 示例虚拟内存统计信息,包括可用页面、`pbuf` 使用情况和 `fsbuf` 使用情况。
文章
Claire Zheng · 一月 20, 2021

使用内置的REST API监控InterSystems IRIS

我们不必等待SAM发布才开始规划和试用该API来监控IRIS实例。在以后的文章中,我将更深入地探讨可用的指标及其意义,并提供一些交互式仪表板的示例。首先,我将介绍一下相关背景和一些问题及答案。 IRIS(和Caché)一直在收集自身及其运行平台的数十个指标。收集这些指标来监控Caché和IRIS的方法向来有很多。我发现,很少有安装软件使用IRIS和Caché的内置解决方案。譬如,History Monitor作为性能和系统使用指标的历史数据库,已经推出很长时间了,但它没有简便方法可实时显示这些指标和仪表系统。 IRIS平台解决方案(以及整个业界)正在从仅在一些本地实例上运行的单体式应用程序过渡到“随处”部署的分布式解决方案。在许多用例中,原有的IRIS监控方案并不适用于这些新的模式。InterSystems没有做重复工作,而是将目光投向当前流行的、经过验证的监控和告警开源解决方案。 Prometheus? Prometheus是一个基于成熟技术、应用广泛的著名开源监控系统,具有多种多样的插件。Prometheus的设计目的是在云环境中很好地运行,但它同样适用于本地环境。Prometheus的插件包括操作系统、web服务器(如Apache)和许多其他的应用程序。Prometheus通常与前端客户端(如Grafana)一起使用,后者可提供极具定制性的一流UI/UX体验。 Grafana? Grafana也是开源平台。随着本系列文章的深入,我将提供常见场景监控仪表板的示例模板。在这些示例模板的基础上,你可以进一步设计自己想要的各种仪表板。将IRIS指标与你的整个解决方案堆栈的各项指标适当结合,就可以发挥真正的威力;各项指标来自于平台组件、操作系统、IRIS,尤其是当你在应用程序中添加仪表功能的时候。 我以前见过这种方法吗? 使用Prometheus和Grafana监控IRIS与Caché并不是新出现的方法。几年来,我一直使用这些应用程序监控我的开发和测试系统。在开发者社区中搜索“Prometheus”,就可以找到一些其它文章,这些文章讲述了如何显示Caché指标,以供Prometheus使用。 跟过去不同的是,现在的/api/monitor API是内置的,而且默认启用。用户无需为显示指标而自己编写类。 Prometheus入门 在这里简单介绍一下Prometheus和一些术语。希望读者能够深入学习并打下一定基础,这将有助于你思考如何运用IRIS或其他来源提供的各项指标或将其可视化。 Prometheus的工作方式是抓取或提取由作为HTTP端点的应用程序(IRIS /api/monitor等API)所公开的时间序列数据。现有的导出器和客户端库适用于多种语言、框架、开源应用程序(例如Apache等web服务器)、操作系统、docker、Kubernetes、数据库和现在的IRIS。 导出器用于将应用程序和服务仪表化,并公开端点上的相关指标以进行抓取。核心导出器支持各种标准组件,例如web服务器、数据库等。其他多种开源导出器可从Prometheus社区获取。 Prometheus术语 有几个关键术语需要了解: ·目标 是指你关心的服务所处的位置,例如主机、应用程序或服务(如:Apache、IRIS或你自己的应用程序)。 ·Prometheus 通过HTTP抓取目标,以收集指标作为时间序列数据。 ·时间序列数据 是通过应用程序(如IRIS)或导出器公开的。 ·导出器 可用于你无法控制的数据,譬如Linux内核指标。 ·生成的时间序列数据 存储在本地Prometheus服务器上的一个数据库中**。 ·这个时间序列数据库 可以使用优化的查询语言(PromQL)进行查询,以便创建警报或者由客户端应用程序(如Grafana)在仪表板中显示指标等。 **剧透警告:出于安全性、扩展性、高可用性及运营效率方面的考虑,在新的SAM解决方案中,Prometheus时间序列数据所使用的数据库是IRIS数据库!但对IRIS平台的Prometheus数据库的访问是透明的,而应用程序(如Grafana)对这些访问既不知道也不关心。 Prometheus数据模型 该API返回的指标是Prometheus格式的。Prometheus采用基于文本的简单指标格式,每行一个指标,格式如下: [ (timen, valuen), ....] 指标可将标签作为(键,值)对,而标签是将指标作为维度过滤的强大方法。例如,检验IRIS /api/monitor返回的一个指标──日志可存储空间: iris_jrn_free_space{id="WIJ",dir=”/fast/wij/"} 401562.83 标识符反映了指标的含义和来源: iris_jrn_free_space 多个标签可用于修饰指标,然后用来过滤和查询。在这个例子中,可以看到WIJ及其存储目录: id="WIJ",dir="/fast/wij/" 此外,还有一个值:401562.83(MB)。 有哪些IRIS指标可供使用? 预览版文档资料中含有一个指标列表。但要注意,其中的内容可能会有所调整。你也可以查询/api/monitor/metrics端点以查看列表。我使用的是Postman,关于这一点,我将在下一篇文章中进行阐述。 我应该监控什么? 考虑怎样监控你的系统和应用程序时,请记住以下要点: 1. 尽可能将影响用户的关键指标仪表化 o用户并不关心你的某台机器是否缺少CPU。 o用户关心的服务是否缓慢或出错。 o你的主仪表板应显示那些直接影响用户的高级指标。 2. 仪表板应避免显示大量图表 o人无法一次性处理太多数据。 o例如:每项服务都有一个仪表板。 3. 关注服务,而不是机器 o将问题定位到某项服务之后,你就可以接着往下找原因,看看是否是哪台机器出了问题。 参考资料 文档资料和下载 Prometheus:https://prometheus.io/ Grafana:https://grafana.com/ 在InterSystems 2019年全球峰会上,我简要介绍了预发布版SAM(包括Prometheus和Grafana);你可以在InterSystems学习服务网站上找到相关链接。如果此链接无效,请访问InterSystems学习服务网站,并搜索:“System Alerting and Monitoring Made Easy”。 你也可以在社区中搜索“Prometheus”和“Grafana”。 注:本文为译文,欢迎点击阅读原文,原文由Murray Oldfield撰写
公告
Claire Zheng · 二月 1, 2021

InterSystems多模型数据库竞赛优胜者已产生!

亲爱的社区用户,大家好! InterSystems多模型数据库竞赛 已圆满结束,感谢大家积极参加这次编程马拉松! 现在,我们来宣布此次竞赛优胜者! 下面这些开发者及其开发的应用值得拥有雷鸣般的掌声!!! 🏆专家提名奖(Experts Nomination) - 获奖者由我们特别挑选的专家团选出: 🥇 第一名,$2,000 的获奖者 @José.Pereira ,提交项目为:iris-image-index-demo 🥈 第二名,$1,000 的获奖者@MikhailenkoSergey ,提交的项目为: zapm 🥉 第三名, $500 的获奖者 @Renato.Banzai ,提交的项目为: iris-multimodel-suite 🏆 社区提名奖(Community Nomination) - 获得总投票数最多的应用: 🥇 第一名,$1,000的获奖者@Botai.Zhang ,提交的项目为: HealthInfoQueryLayer 🥈 第二名,$500 的获奖者 @Henrique.GonçalvesDias ,提交的项目为: iris-vaccine-tracker 🥉 第三名,$250 的获奖者@José.Pereira ,提交的项目为: iris-image-index-demo 恭喜所有获奖用户! 感谢您对本次大赛的关注,感谢您在这场令人兴奋的编程大赛中付出的努力! 接下来呢? 我们的 InterSystems 编程大奖赛! 已经开始了 奖金总额: $16,000 加入大奖赛,不见不散哦😉 热烈恭喜@Botai Zhang!
公告
Claire Zheng · 三月 8, 2021

InterSystems中文社区编程大奖赛获奖项目简介

InterSystems编程大奖赛取得圆满成功,来自中文社区的两位参赛者获得项目奖励,项目简介如下。 获奖者@Botai Zhang 获奖情况:获得专家提名奖(Experts Nomination)第三名和社区提名奖(Community Nomination)第一名 提交项目:HealthInfoQueryLayer(基于Intersystems IRIS平台整合医院信息查询业务解决方案) 项目简介:随着医院信息化建设的逐步完善,医院子系统越来越多,系统间接口越来越多,同时接口费用不断增加,管理工作变得越来越复杂。其中,查询类业务接口根据业务类型分化,数量也是逐步递增,带来接口量大、开发工作繁重、代码冗余、维护困难等等问题。针对这一困境,我们基于Intersystems IRIS数据平台整合医院信息查询业务解决方案。该应用程序可通过配置完成查询业务接口实现,大大缩小开发、维护、实施等项目关键运转周期。 欢迎移步项目链接了解更多详情: HealthInfoQueryLayer 获奖者@Weiwei Yang获奖情况:社区提名奖(Community Nomination)第二名提交项目:Dictionary comparison scheme of cache database项目简介(应用场景):现场需要将各个科室部门内的数据统一汇总到医院总部,但是汇总后发现各个科室使用的字典并不统一,需要将表中的现存的字典统一更换为医院制定字典。例如:A科室中人员的性别字典使用0/1/2表示各种性别,B科室中性别字典使用F/M/O表示各种性别,但是现在医院要求所有性别字典保存Female/Male/Other性别信息,此时就需要替换原有的性别字典为新用字典。当初,此处只是列举了一个使用场景,未来有多个需要对照字典的工作都可以考虑此项目的设计和实现思想。欢迎移步项目链接了解更多详情:Dictionary comparison scheme of cache database
问题
Michael Lei · 五月 13, 2021

是否有任何Spark或Kafka连接InterSystems Iris Source?

我找不到在Internet上连接到InterSystems Iris的spark或Kafka的情况。是否可以共享任何相关资源? InterSystems 提供一个专门的 Spark connector. Documentation. 当然也可以用 JDBC 驱动 以下是一些IRIS--Kafka 互操作性的例子: PEX Demo Kafka demo
公告
jieliang liu · 四月 20, 2022

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

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

InterSystems广播站第一期——什么是IRIS?欢迎收听!

说明 欢迎来到InterSystems广播站--数据点!在这一集里,我们和在线培训团队负责人Jenny Ames聊了聊InterSystems IRIS--稳定、灵活、可扩展、可互操作的数据平台,它为世界上许多最关键的核心应用提供支持。从它的多模型性质到它的集成引擎,再到它的医疗保健功能,在一次谈话中,有很多东西需要解读。 本期节目回放:https://datapoints.castos.com/episodes/1-what-is-intersystems-iris-jenny-ames 关于InterSystems广播站的更多信息,请访问https://datapoints.intersystems.com。 今天就试用InterSystems IRIS,请到https://www.intersystems.com/try,启动你的实例! 更多资料欢迎访问:https://gettingstarted.intersystems.com。 以下是本期对话中文全文。 德里克-罗宾逊 00:01 欢迎来到InterSystems 在线培训的播客。请确保在你最喜欢的播客应用程序上订阅播客,如Spotify、苹果播客、谷歌播放或Stitcher。你可以通过搜索 "数据点 "并点击订阅按钮来做到这一点。我是Derek Robinson,在今天的节目中,我将与InterSystems在线培训团队负责人Jenny Ames谈论InterSystems IRIS数据平台。 Derek Robinson 00:39 欢迎来到InterSystems在线培训广播站《数据点》第一集。我的名字是Derek Robinson。我是InterSystems公司的一名在线培训课程开发人员,我们学习服务部的所有人都对推出这个播客节目感到非常非常兴奋。我们有多集不同的节目将陆续推出,所以在你听完这一集后一定不要错过其他的节目。在这一集里,我将与Jenny Ames聊天。正如我在介绍中提到的,Jenny是在线培训团队负责人,她在我们的技术栈方面有超过10年的经验。因此,在我们的讨论中,我们将介绍InterSystems IRIS的基本情况,它的一些最佳功能是什么,以及她所看到的一些最佳使用案例。我们将概要地聊聊这个产品是什么,它的一些医疗行业的扩展是什么,以及它如何能够真正帮助你作为一个开发者的应用开发,开发数据驱动和数据密集型应用。闲话少说,下面是我对Jenny Ames的采访。 德里克-罗宾逊 01:36 欢迎Jenny Ames来到播客室,她是InterSystems在线培训服务的团队负责人。Jenny,你好吗? 珍妮-艾姆斯 嗨,德里克。我很好。你呢? 德里克-罗宾逊 好。我也很好。我们很高兴推出InterSystems广播站--数据点,并邀请你作为我们的首批嘉宾之一,在这里谈论InterSystems IRIS,以及它对于那些可能不知道的人来说是什么,还有对于那些有兴趣了解更多的InterSystems用户,以及我们技术栈的背景。首先,请您先介绍一下自己,让我们知道你在InterSystems是做什么的,你在这里工作了多长时间,以及你在InterSystems世界的经验? Jenny Ames 02:07 当然,是的。所以我在2020年6月份刚刚庆祝了10年。前五年,我是一名培训讲师,培训我们大部分的产品。Caché、Ensemble、Health Connect以及大部分的HealthShare课程,我非常喜欢这些课程,但是一些生活上的变化意味着我想在这里多待一会儿,所以在过去的五年半里,我一直在做在线培训。 德里克-罗宾逊 02:33 不错。这真是太棒了。所以你显然非常适合我们今天要讨论的问题。那么,让我们从InterSystems IRIS数据平台是什么这个问题开始,好吗?您可以先为那些从未见过它的听众用一个概要性的例子或描述一下IRIS吗?然后我们可以更详细地去了解它的一些功能是什么。所以,如果我今天在电梯里看到你,问你什么是InterSystems IRIS,你会怎么回答? Jenny Ames 02:58 好的,我喜欢把InterSystems IRIS分成三个主要部分。首先它是一个强大的数据库,可以存储、检索数据。它有一个内置的开发环境来构建业务逻辑。同时它也是一个集成引擎,所以你可以在不同的系统之间非常容易地分享数据,进行互联互通,有一些很好的用户界面UI可以帮助你快速地做到这一点,而无需太多的代码。你也可以定制它,因为我们有很好的数据库层面的支持。然后,它也是一个数据分析平台,你可以建立机器学习模型来显示仪表盘和分析数据,以真正使你的数据有意义,并且持续在这个基础上建立新的分析。我们还包含了自然语言处理NLP功能。可以分析大段的文本,找到积极的东西或总结文本。 Derek Robinson 03:52 是的。在今天,整合不断的信息流从各种不同的来源进入你的应用程序,这变得越来越重要,真实世界并不总是像传统的关系型数据库中那样严谨地定义属性和排列,那需要你知道所有的属性和一切,对吗?所以你总整体上总结了这三个方面。下面,让我们从数据库部分开始,因为我认为任何要建立一个数据密集型应用程序的应用开发者都需要从数据库开始,对吗?比如他们需要他们的数据在某个地方。那么,在进入其他功能之前,仅从数据库的角度来看,InterSystems IRIS与人们可以选择的其他数据库相比有什么区别? Jenny Ames 04:30 是的,这是个好问题。首先,我们在InterSystems IRIS中内置了一些逻辑,所以你可以直接利用来建立业务。如果你熟悉Caché,这是我们已经推出一段时间的产品之一,IRIS里有一些新的东西是一些语言的互操作性部分,所以你仍然可以利用你其他用Java.net、Python或Node.js构建的应用程序,然后与InterSystems IRIS的数据库平台进行整合。但我想说的是,真正让它脱颖而出的特性是可靠性。我们在全球主流市场,比如医疗、金融,我们能成功的主要原因就是因为它的可靠性。这是因为我们拥有的可靠性和内置的安全性。 Derek Robinson 05:27 对,没错。因此,对于任何使用数据库来建立他们的应用程序和托管他们的数据并真正能够使用他们的数据的人来说,那里有一些好的元素和好的要求。还有一点,我想谈谈,我知道这与语言的互操作性有一点关系,当涉及到为你的数据库使用不同的模型时,也是模型的灵活性。我知道,当我们在活动中与开发人员交谈时,有时会让他们停下来说,等等,告诉我更多关于这个问题。所以,请给我一个快速的例子,描述一下InterSystems IRIS在数据库层面的多模型能力。 Jenny Ames 06:00 是的。因此,多模型......大多数数据库都选择支持一种模型,无论是对象型数据库还是关系型数据库。而我们认为,为什么要选择?通过对象访问或通过二维表来访问数据有不同的原因。从像Java这样的东西来看,它已经是一个对象模型。所以能够直接保存一个对象是一个巨大的好处,因为它既节省了开发者的时间,也节省了转化时间, 它不必将数据转化为关系型、转化为行就能够做到这一点。但是做一些事情,比如说,选择所有在一家公司工作的人,这种数据用关系型模型来做就真的很容易。因此,我们的设计理念,是使用对每项任务最有效的模型,然后将其全部整合到一个应用程序和平台中。 Derek Robinson 06:45 对。不需要为了解决同一问题或者问题中的不同变化而建立或重复不同的方法,这真的很酷。顺便说一句,沿着这个话题,我想未来的一集可能会涉及到更深层次的内容,即我们的Global和有效的工作方式。我想到了一两个人,他们会很好地解释InterSystems的这些概念,但要更多地讨论InterSystemsInterSystems产品的整体形象。我知道我们以前参加过一些活动,人们会看到我们的商标,看到我们的品牌,然后他们就把InterSystems归类到到医疗行业。对吗?看起来你们是一家医疗IT公司,所以这很酷。可以再跟我说说,为什么人们不应该因为我们做医疗行业把我们只归类在医疗行业?如果有人不在医疗行业领域,有什么理由让他们不应该立即认为InterSystems真的只是医疗信息IT软件? Jenny Ames 07:38 是的。我们在医疗领域的成功是有原因的。同样,因为我们在InterSystems IRIS和其他产品中建立的可靠性、可扩展性和安全性。所以,是的,我们进入其他领域也是有原因的。因为这些功能在多个垂直领域真的很重要。比如,金融机构,你知道,钱对人们来说真的很重要,所以能够使用InterSystems IRIS和利用这些特性真的很重要。而且,就像我提到的,我在教室里的前五年,我已经看到了一些不同的使用案例,我认为我们的一些客户真的很酷。比如说有一家汽车制造公司,他们基本上是集成和处理汽车零件,并能够管理所有这些零部件数据。他们基本上从多个不同的警察辖区获取数据,这些数据以不同的格式存储,他们必须转换这些数据。把所有的数据用我们的产品管理起来,然后他们在此基础上建立了仪表盘,以便能够分析数据并利用数据本身做一些非常酷的事情。 Derek Robinson 09:00 有意思。是的,我认为你提到的最后一个用例可以作为深入讨论我们IRIS的互操作性功能的基础,对吗?我认为还有很多我们可以深入讨论的地方,比如你提到把数据转化为正确的格式。其中有一些转化是我们开始进入那些医疗行业功能的核心,也是我们在医疗行业中最需要的东西。那么,你对这部分还有什么要补充的吗? Jenny Ames 09:26 是的。我们有一些内置的功能,在医疗等行业,一些预置的组件方面确实有帮助。但我们也一直在建立更多的功能,在那里你可以做一些事情,如记录映射器,无代码集成数据等等。但同样,你也可以完全定制它,以便能够使数据具有正确的格式。但是,互操作性实际上是让我最兴奋的功能。我真的很喜欢,我实际上有很多的乐趣,建立集成,玩这个,自己学习更多。但是,是的,我真的很喜欢InterSystems IRIS的这个功能。 Derek Robinson 10:00 是的。在使用案例之前,还有一件事......我们马上要讲到医疗行业,但是经常谈到的InterSystems IRIS的其他使用案例之一是欧洲航天局,它突出了InterSystems IRIS的一些可扩展性、可靠性和处理这些数据负载的巨大能力。 这是一个我们已经谈了很多的例子。你能给我们讲讲这个用例,这个例子,以及为什么它能有效地展示InterSystems IRIS的能力? Jenny Ames 10:29 是的,欧空局使用了我们的一个产品,InterSystems IRIS也采用了其中最好的功能,非常酷。几年前有一个很好的演示,我去看了,就是他们在太空中放置的这个东西,它实际上非常小。比如你可以......你现在看不到我,但是它也许是足球大小,或者可能比它小一点。它基本上绘制了整个银河星系的地图,而且,你知道,对于亮度和速度以及所有这些不同的天体。然后它把这些数据带回来,让操作人员上分析这些数据,真正绘制银河系,这真的很酷。但是,是的,我认为这是一个非常漂亮的例子,因为它正在处理大量的数据,在“大数据”这个词被创造出来之前我们已经在做大数据,但这不是最酷的,最酷的是你拥有所有的数据能够真正发挥他们的作用。 德里克-罗宾逊 11:38 对。很好。作为对我们学习者的一点提示,要想更多地了解这些功能,一般来说,我们只是在谈论可扩展性和可靠性。在可扩展性方面,当涉及到横向扩展系统时,你真的可以看一下分片,以了解更多。我不想深究这个问题,因为我们会有关于这个问题的其他专题。对于可靠性来说,我们的可靠性是镜像技术,对吧?就像我认为你所提到的系统的可靠性,如果一个系统发生故障,也许这种镜像能力是InterSystems产品的特点之一。我有时会说IRIS,但我们谈论的确实是我们大部分的技术堆栈,这些技术对于那些可扩展性和可靠性的一些功能来说确实是最基本的。所以,在这里,我们要进入最后一个部分,也就是IRIS医疗版。InterSystems IRIS for Health是InterSystems IRIS的医疗扩展,是一个更强大的平台。请告诉我们InterSystems IRIS for Health在医疗领域的一些具体扩展功能。 Jenny Ames 12:46 是的。IRIS for Health是InterSystems的IRIS医疗版,它确实是专门为医疗行业打造的,所以它有许多预置的医疗行业特性,帮助你整合并真正为医疗行业环境建立整个数字化应用。它包括对HL7 v2等事务的预建支持,你可以根据事件引入不同的消息。我们有对FHIR的支持。有一个内置的FHIR资源库来管理所有的资源。如果你不熟悉这些术语,你可以百度一下,了解一下。实际上,我们也有一些关于它的课程,你可以参加。我们有对IHE的支持,所以我们的许多针对医疗行业的支持都是内置的,它使你更容易集成不同的数据和应用和更快搭建医疗行业应用程序。 德里克-罗宾逊 13:45 对。很好。我想说的是,珍妮提到的学习内容,即learning.intersystems.com,是我们的学习目录所在。我想这是在这些播客和所有东西的介绍中的一种。但是说到更多的学习和呼吁行动,我们在这里想谈的最后一件事是,我们一直在谈论InterSystems IRIS和InterSystems产品的整体情况。如果我们的一些听众很好奇,他们想了解更多的情况,人们如何才能尝试IRIS? 珍妮-艾姆斯 14:08 是的。我们有两个很棒的新东西可以使用。有一个 "试用IRIS实例"。这基本上是一个试用实例,你可以免费获得,如果你不注册,它可以使用24小时。但如果你注册了,你可以保留30天,这真的很不错。你可以亲身体验,里面有一些预制的样本。所以要访问这个网站,你可以去intersystems.com/try,右边有一个按钮,你可以开始编码。然后还有一个网站,实际上与此有关。在这个屏幕的左侧,有一个新的按钮,可以进入我们新的入门网站。所以,如果你去gettingstarted.intersystems.com,你可以直接去那里,同样,那里有练习和一些使用案例视频,所以你可以开始想象使用InterSystems IRIS的不同方式。 Derek Robinson 14:57 真棒!对于我们的听众,我们会把这些链接放在节目描述中,这样你就可以直接进入这些页面,无论是尝试页面还是入门页面,以真正了解InterSystems IRIS的情况。所以,Jenny Ames,今天的时间就先到这里,非常感谢你参加我们的节目,我们期待和您再次访谈。 Jenny Ames 很好。谢谢邀请! Derek Robinson 15:16 所以再次感谢Jenny加入我们,就InterSystems IRIS和InterSystems IRIS for Health进行了一次内容丰富的谈话,最后还谈到了它对开发人员构建这些数据驱动型应用程序的最大帮助,他们可能需要与其他系统的互操作性,转换你在其他应用程序之间发送或接收的数据。拥有一个非常可靠的设置,如果有什么东西发生故障,或者你需要比你目前拥有的更大的规模,可以真正依靠它。因此,与Jenny就InterSystems IRIS进行了很好的讨论,并再次感谢她。就像我在介绍中提到的,我们在目录中还有很多集,您现在就可以听,然后随着我们的发展,就像我们在预告片中提到的,我们将寻求每月做一到两集,而且真的就像我们可以从我们的专家那里获取内容一样,这就是我们的计划,能够给你提供信息和有趣的讨论,帮助大家学习更多。所以,重要的事情说三遍,你可以到intersystems.com/try或gettingstarted.intersystems.com去试试InterSystems IRIS,至于一般的学习内容,可以到learning.intersystems.com去看看我们的全部目录,同样,在你喜欢的播客应用程序上搜索Data Points并点击订阅按钮。这样,每当我们有新的节目时,你就会收到每一集。再次感谢您的收听,我们将在InterSystems广播站《数据点》节目中再见。 本期节目回放:https://datapoints.castos.com/episodes/1-what-is-intersystems-iris-jenny-ames 关于InterSystems广播站的更多信息,请访问https://datapoints.intersystems.com。 今天就试用InterSystems IRIS,请到https://www.intersystems.com/try,启动你的实例! 更多资料欢迎访问:https://gettingstarted.intersystems.com。
文章
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
文章
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 的消息。 在下一篇文章中,我们将讨论创建此跟踪中显示的“消息”背后的概念以及如何实际定义它。