#最佳实践

0 关注者 · 10 帖子

关于如何在 InterSystems 数据平台上更好地开发、测试、部署和管理解决方案的最佳实践建议。

文章 Claire Zheng · 十一月 11, 2025 7m read

实时 FHIR® 到 OMOP 转换

OMOP 之旅的这一部分,我们在尝试挑战Scylla 之前先反思一下,InterSystems OMOP 转换是建立在批量 FHIR 导出作为源有效载荷的基础上的,我们是多么幸运。 这开启了 InterSystems OMOP 转换与多个 FHIR® 供应商的放手互操作性,这次是与谷歌云医疗 API 的互操作性

谷歌云医疗 API FHIR® (Google Cloud Healthcare API FHIR®)导出

GCP FHIR® 数据库支持通过命令行界面(CLI)或应用程序编程接口(API)进行FHIR数据的批量导入/导出,其前提条件很简单,且相关文档极为详尽,因此我们就不让模型再针对这方面进行赘述训练了,如有兴趣,我们会附上相关链接。 本段标题中更有价值的是bulk FHIR export (批量FHIR导出)标准本身的实现。

谷歌实施 FHIR® 导出的重要区别在于:通过 Pub/Sub 发送资源变更通知,以及指定增量导出的能力。

实时?

是的!我想我会死在这把剑上的。 这不仅是我的说唱手柄,而且其机制绝对可以支持一个很好的技术论证,可以说...

"当一个新的组织被创建到 FHIR 时,我们会对其进行转换,并将其添加到 InterSystems OMOP CDM 中,与 Care_site/location 一样"。

演练

0
0 7
文章 Michael Lei · 九月 27, 2024 9m read

在这一系列文章中,我想向大家介绍并探讨使用 InterSystems 技术和 GitLab 进行软件开发可以采用的几种方式。 我将介绍以下主题:

  • Git 101
  • Git 流程(开发流程)
  • GitLab 安装
  • GitLab 工作流
  • 持续交付
  • GitLab 安装和配置
  • GitLab CI/CD
  • 为何使用容器
  • 容器基础架构
  • 使用容器的 CD

第一篇文章中,我们介绍了 Git 基础知识、深度理解 Git 概念对现代软件开发至关重要的原因,以及如何使用 Git 开发软件。

第二篇文章中,我们介绍了 GitLab 工作流 – 一个完整的软件生命周期流程,并介绍了持续交付。

第三篇文章中,我们介绍了 GitLab 安装和配置以及将环境连接到 GitLab

第四篇文章中,我们编写了 CD 配置。

第五篇文章中,我们讨论了容器以及使用容器的方式(和原因)。

第六篇文章中,我们将探讨运行包含容器的持续交付管道所需的主要组件以及这些组件如何协同运行。

在这篇文章中,我们将构建上一篇文章中探讨的持续交付配置。

工作流

在持续交付配置中,我们会:

  • 将代码推送到 GitLab 仓库
  • 构建 docker 镜像
  • 进行测试
  • 将镜像发布到 docker 注册表
  • 将旧容器换为注册表中的新版本

也可以用示意图形式表示此流程:

我们开始吧。

构建

首先,我们需要构建镜像。

我们的代码通常存储在仓库中,CD 配置位于 gitlab-ci.yml 中,但为了提高安全性,我们会在构建服务器上存储几个服务器特定的文件。

GitLab.xml

包含 CD 挂钩代码。 该代码是在上一篇文章中开发的,并在 GitHub 上提供。 这是一个小型库,用于加载代码、运行各种挂钩以及测试代码。 作为更好的替代方案,您可以使用 git 子模块将此项目或类似项目包含到您的仓库中。 最好选择子模块,因为子模块更容易保持最新状态。 另一个替代方案是在 GitLab 上为版本添加标签,并使用 ADD 命令加载这些版本。

iris.key

许可证密钥。 或者,它可以在容器构建过程中下载,而不是存储在服务器上。 将密钥存储在仓库中非常不安全。

pwd.txt

包含默认密码的文件。 将这类文件存储在仓库中也非常不安全。 此外,如果您在单独的服务器上托管生产环境,它可能有不同的默认密码。

load_ci.script

初始脚本,它执行以下任务:

  • 实现操作系统身份验证
  • 加载 GitLab.xml
  • 初始化 GitLab 实用工具设置
  • 加载代码

set sc = ##Class(Security.System).Get("SYSTEM",.Properties) write:('sc) $System.Status.GetErrorText(sc) set AutheEnabled = Properties("AutheEnabled") set AutheEnabled = $zb(+AutheEnabled,16,7) set Properties("AutheEnabled") = AutheEnabled set sc = ##Class(Security.System).Modify("SYSTEM",.Properties) write:('sc) $System.Status.GetErrorText(sc) zn "USER" do ##class(%SYSTEM.OBJ).Load(##class(%File).ManagerDirectory() _ "GitLab.xml","cdk") do ##class(isc.git.Settings).setSetting("hooks", "MyApp/Hooks/") do ##class(isc.git.Settings).setSetting("tests", "MyApp/Tests/") do ##class(isc.git.GitLab).load() halt

请注意,第一行有意留空。

由于某些设置可以是服务器特定的,脚本不会存储在仓库中,而是单独存储。 如果此初始挂钩始终相同,将其存储在仓库中即可。

gitlab-ci.yml

现在,继续持续交付配置:

构建镜像:
  stage: build
  tags:
    - test
  script:
    - cp -r /InterSystems/mount ci
    - cd ci
    - echo 'SuperUser' | cat - pwd.txt load_ci.script > temp.txt
    - mv temp.txt load_ci.script
    - cd ..
    - docker build --build-arg CI_PROJECT_DIR=$CI_PROJECT_DIR -t docker.domain.com/test/docker:$CI_COMMIT_REF_NAME .

这里会执行哪些操作?

首先,由于 docker build 只能访问基础构建目录的子目录(本例中是仓库根目录),我们需要将“秘密”目录(包含 GitLab.xmliris.keypwd.txt 和 load_ci.script 的目录)复制到克隆的仓库中。

接下来,首次终端访问需要用户名/密码,因此我们会将这些信息添加到 load_ci.script 中(这也是 load_ci.script 开头一行留空的原因)。

最后,我们会构建 docker 镜像并适当地为其添加标签:docker.domain.com/test/docker:$CI_COMMIT_REF_NAME

其中,$CI_COMMIT_REF_NAME 是当前分支的名称。 请注意,镜像标签的第一部分应与 GitLab 中的项目名称相同,这样才能在 GitLab 的“注册表”标签页中看到它(“注册表”标签页中提供了关于添加标签的说明)。

Dockerfile

构建 docker 镜像是通过 Dockerfile 完成的,具体如下:

FROM docker.intersystems.com/intersystems/iris:2018.1.1.611.0

ENV SRC_DIR=/tmp/src ENV CI_DIR=$SRC_DIR/ci ENV CI_PROJECT_DIR=$SRC_DIR

COPY ./ $SRC_DIR

RUN cp $CI_DIR/iris.key $ISC_PACKAGE_INSTALLDIR/mgr/
&& cp $CI_DIR/GitLab.xml $ISC_PACKAGE_INSTALLDIR/mgr/
&& $ISC_PACKAGE_INSTALLDIR/dev/Cloud/ICM/changePassword.sh $CI_DIR/pwd.txt
&& iris start $ISC_PACKAGE_INSTANCENAME
&& irissession $ISC_PACKAGE_INSTANCENAME -U%SYS < $CI_DIR/load_ci.script
&& iris stop $ISC_PACKAGE_INSTANCENAME quietly

我们从基本的 iris 容器开始。

首先,我们将仓库(和“秘密”目录)复制到容器中。

接下来,我们将许可证密钥和 GitLab.xml 复制到 mgr 目录中。

然后,我们将密码更改为 pwd.txt 中的值。 请注意,此操作会删除 pwd.txt。

之后,实例启动并执行 load_ci.script。

最后,iris 实例停止。

以下是作业日志(部分日志,跳过了加载/编译日志):

Running with gitlab-runner 10.6.0 (a3543a27)
  on docker 7b21e0c4
Using Shell executor...
Running on docker...
Fetching changes...
Removing ci/
Removing temp.txt
HEAD is now at 5ef9904 Build load_ci.script
From http://gitlab.eduard.win/test/docker
   5ef9904..9753a8d  master     -> origin/master
Checking out 9753a8db as master...
Skipping Git submodules setup
$ cp -r /InterSystems/mount ci
$ cd ci
$ echo 'SuperUser' | cat - pwd.txt load_ci.script > temp.txt
$ mv temp.txt load_ci.script
$ cd ..
$ docker build --build-arg CI_PROJECT_DIR=$CI_PROJECT_DIR -t docker.eduard.win/test/docker:$CI_COMMIT_REF_NAME .
Sending build context to Docker daemon  401.4kB

Step 1/6 : FROM docker.intersystems.com/intersystems/iris:2018.1.1.611.0 ---> cd2e53e7f850 Step 2/6 : ENV SRC_DIR=/tmp/src ---> Using cache ---> 68ba1cb00aff Step 3/6 : ENV CI_DIR=$SRC_DIR/ci ---> Using cache ---> 6784c34a9ee6 Step 4/6 : ENV CI_PROJECT_DIR=$SRC_DIR ---> Using cache ---> 3757fa88a28a Step 5/6 : COPY ./ $SRC_DIR ---> 5515e13741b0 Step 6/6 : RUN cp $CI_DIR/iris.key $ISC_PACKAGE_INSTALLDIR/mgr/ && cp $CI_DIR/GitLab.xml $ISC_PACKAGE_INSTALLDIR/mgr/ && $ISC_PACKAGE_INSTALLDIR/dev/Cloud/ICM/changePassword.sh $CI_DIR/pwd.txt && iris start $ISC_PACKAGE_INSTANCENAME && irissession $ISC_PACKAGE_INSTANCENAME -U%SYS < $CI_DIR/load_ci.script && iris stop $ISC_PACKAGE_INSTANCENAME quietly ---> Running in 86526183cf7c . Waited 1 seconds for InterSystems IRIS to start This copy of InterSystems IRIS has been licensed for use exclusively by: ISC Internal Container Sharding Copyright (c) 1986-2018 by InterSystems Corporation Any other use is a violation of your license agreement

%SYS> 1

%SYS> Using 'iris.cpf' configuration file

This copy of InterSystems IRIS has been licensed for use exclusively by: ISC Internal Container Sharding Copyright (c) 1986-2018 by InterSystems Corporation Any other use is a violation of your license agreement

1 alert(s) during startup. See messages.log for details. Starting IRIS

Node: 39702b122ab6, Instance: IRIS

Username: Password:

Load started on 04/06/2018 17:38:21 Loading file /usr/irissys/mgr/GitLab.xml as xml Load finished successfully.

USER>

USER>

[2018-04-06 17:38:22.017] Running init hooks: before

[2018-04-06 17:38:22.017] Importing hooks dir /tmp/src/MyApp/Hooks/

[2018-04-06 17:38:22.374] Executing hook class: MyApp.Hooks.Global

[2018-04-06 17:38:22.375] Executing hook class: MyApp.Hooks.Local

[2018-04-06 17:38:22.375] Importing dir /tmp/src/

Loading file /tmp/src/MyApp/Tests/TestSuite.cls as udl

Compilation started on 04/06/2018 17:38:22 with qualifiers 'c' Compilation finished successfully in 0.194s.

Load finished successfully.

[2018-04-06 17:38:22.876] Running init hooks: after

[2018-04-06 17:38:22.878] Executing hook class: MyApp.Hooks.Local

[2018-04-06 17:38:22.921] Executing hook class: MyApp.Hooks.Global Removing intermediate container 39702b122ab6 ---> dea6b2123165 [Warning] One or more build-args [CI_PROJECT_DIR] were not consumed Successfully built dea6b2123165 Successfully tagged docker.domain.com/test/docker:master Job succeeded

请注意,我使用的是 GitLab Shell 执行器,而不是 Docker 执行器。 当您需要从镜像内部提取某些内容时,将使用 Docker 执行器,例如在 Java 容器中构建 Android 应用程序并且只需要一个 apk 时。 在我们的示例中,我们需要整个容器,因此需要使用 Shell 执行器。 因此,我们通过 GitLab Shell 执行器运行 Docker 命令。

 

运行

我们构建了镜像,接下来要运行镜像。如果是功能分支,我们销毁旧容器并启动新容器即可。 如果是环境,我们可以运行临时容器,在测试成功的情况下,可以替换环境容器(此内容留给读者作为练习)。

脚本如下。

destroy old:
  stage: destroy
  tags:
    - test
  script:
    - docker stop iris-$CI_COMMIT_REF_NAME || true
    - docker rm -f iris-$CI_COMMIT_REF_NAME || true

此脚本会销毁当前运行的容器,并且始终都会成功(默认情况下,如果 docker 尝试停止/移除不存在的容器,则会失败)。

接下来,我们启动新镜像并将其注册为环境。 Nginx 容器 使用 VIRTUAL_HOST 环境变量和 expose 指令(用于了解要代理的端口)自动代理请求。

run image:
  stage: run
  environment:
    name: $CI_COMMIT_REF_NAME
    url: http://$CI_COMMIT_REF_SLUG. docker.domain.com/index.html
  tags:
    - test
  script:
    - docker run -d
      --expose 52773
      --env VIRTUAL_HOST=$CI_COMMIT_REF_SLUG.docker.eduard.win
      --name iris-$CI_COMMIT_REF_NAME
      docker.domain.com/test/docker:$CI_COMMIT_REF_NAME
      --log $ISC_PACKAGE_INSTALLDIR/mgr/messages.log

 

测试

我们来运行一些测试。

test image:
  stage: test
  tags:
    - test
  script:
    - docker exec iris-$CI_COMMIT_REF_NAME irissession iris -U USER "##class(isc.git.GitLab).test()"

发布

最后,我们将镜像发布到注册表中

publish image:
  stage: publish
  tags:
    - test
  script:
    - docker login docker.domain.com -u dev -p 123
    - docker push docker.domain.com/test/docker:$CI_COMMIT_REF_NAME

可以使用 GitLab 秘密变量传递用户名/密码。

现在,我们可以在 GitLab 中看到该镜像:

其他开发者可以从注册表中拉取该镜像。 “环境”标签页上提供了我们所有的环境,可以轻松进行浏览:

 

结论

在这一系列文章中,我介绍了持续交付的常规方式。 这是一个涉及面非常广的话题,您应将这一系列文章视为方法集合,而不是确定性内容。 如果您想自动构建、测试和交付应用程序,可以选择持续交付(一般情况)和 GitLab(特殊情况)。 利用持续交付和容器,您可以根据需要自定义工作流。

链接

后续内容

就是这些! 希望我已介绍了持续交付和容器的基础知识。

但还有一些主题我没有介绍(可能后面会介绍),特别是关于容器的内容:

  • 数据可以在容器外持久保持,以下是相关文档
  • kubernetes 等编排平台
  • InterSystems Cloud Manager
  • 环境管理 – 创建临时环境以进行测试,在功能分支合并后移除旧环境
  • Docker compose 可以实现多容器部署
  • 缩减 docker 镜像大小并缩短构建时间
  • ...
0
0 110
文章 Michael Lei · 九月 26, 2024 7m read

在这一系列文章中,我想向大家介绍并探讨使用 InterSystems 技术和 GitLab 进行软件开发可以采用的几种方式。 我将介绍以下主题:

  • Git 101
  • Git 流程(开发流程)
  • GitLab 安装
  • GitLab 工作流
  • 持续交付
  • GitLab 安装和配置
  • GitLab CI/CD

上一篇文章中,我们介绍了 Git 基础知识、深度理解 Git 概念对现代软件开发至关重要的原因,以及如何使用 Git 开发软件。 我们的侧重点仍是软件开发的实现部分,但本部分会介绍:

  • GitLab 工作流 - 从想法到用户反馈的完整软件生命周期流程
  • 持续交付 – 软件工程方式,团队通过这种方式在短周期内制作软件,从而确保软件可以随时实现可靠发布。 它的目的是更快速、更频繁地构建、测试和发布软件。

GitLab 工作流


GitLab 工作流是软件开发流程整个生命周期中可能采取的操作的逻辑序列。

GitLab 工作流会考虑我们在上一篇文章中探讨的 GitLab 流程。 具体如下:

  1. 想法:每个新提议都始于一个想法。
  2. 问题:探讨想法最有效的方法是为它创建问题。 您的团队和协作者可以在问题跟踪器中帮助您完善和改进问题。
  3. 计划:在讨论达成一致意见后,就可以开始编码了。 但首先,我们需要将问题指定至里程碑和问题看板,以此确定工作流的优先级并进行组织。
  4. 编码:现在,一切安排就绪后,我们就可以编写代码了。
  5. 提交:对草稿满意后,我们便可将代码提交到具有版本控制的功能分支。 上一篇文章详细介绍了 GitLab 流程。
  6. 测试:使用 GitLab CI 运行我们的脚本,以构建并测试应用程序。
  7. 审查:在脚本能够正常运行且测试和构建成功后,我们便可以让代码接受审查并获得批准。
  8. 暂存:现在应该将代码部署到暂存环境,以检查一切是否按预期进行,或者我们是否仍需要进行调整。
  9. 生产:如果一切顺利,便可将代码部署到生产环境!
  10. 反馈:现在可以回顾之前的流程,并检查有哪些阶段的工作需要改进。

再次说明,流程本身不是新的(或者 GitLab 独有的),并且可以通过其他工具来实现。

我们来讨论一下其中的几个阶段以及这些阶段涉及的内容。 还提供文档

问题和计划

GitLab 工作流的开始阶段以问题为中心,问题是指一个功能、一个错误或其他在语义上独立的工作。

问题有多个目的,例如:

  • 管理:问题具有截止日期、指定人员、用时和估计等, 可以帮助跟踪问题解决情况。
  • 行政管理:问题是里程碑的一部分,我们可以通过看板跟踪软件从一个版本过渡到另一个版本的进展。
  • 开发:问题具有与之相关的讨论和提交。

在计划阶段,我们可以按问题的优先级、里程碑、看板将问题分组,并获得问题的概览。

开发在前一部分进行了讨论,只需按照您希望使用的任何 git 流程执行操作即可。 我们开发了新功能并将其合并到 master 分支后,接下来应怎样操作?

持续交付

持续交付是一种软件工程方式,团队通过这种方式在短周期内制作软件,从而确保软件可以随时实现可靠发布。 它的目的是更快速、更频繁地构建、测试和发布软件。 这种方式允许对生产中的应用程序进行更多增量更新,从而帮助缩减交付更改的成本、缩短时间,以及降低风险。 简单且可重复的部署过程对于持续交付非常重要。

GitLab 中的持续交付

在 GitLab 中,持续交付配置按仓库以 YAML 配置文件形式定义。

  • 持续交付配置是一系列连续的阶段
  • 每个阶段都有一个或多个并行执行的脚本

脚本定义了一个操作以及执行该操作需要满足的条件:

  • 要执行的操作(运行 OS 命令、运行容器)?
  • 何时运行脚本:
    • 触发脚本的条件(特定分支)?
    • 之前的阶段失败时是否运行?
  • 手动运行还是自动运行?
  • 脚本在什么环境中运行?
  • 执行脚本后保存哪些工件(这些工件会从环境上传到 GitLab,以便轻松访问)?

环境是配置好的服务器或容器,可用于运行脚本。

运行程序用于在特定环境中执行脚本。 运行程序连接到 GitLab,并根据需要执行脚本。

运行程序可以部署在服务器上、容器上,甚至部署在本地机器上。

持续交付是如何实现的?

  1. 新提交推送到仓库中。
  2. GitLab 检查持续交付配置。
  3. 持续交付配置包含适用于所有情况的全部脚本,因此要过滤出应针对这一特定提交运行的一组脚本(例如提交到 master 分支仅会触发与 master 分支相关的操作)。 这组脚本称为管道
  4. 管道是在目标环境中执行的,执行结果会保存并显示在 GitLab 中。

例如,下面是提交到 master 分支后执行的一个管道:

管道包含四个阶段,各阶段连续执行

  1. 加载阶段会将代码加载到服务器中
  2. 测试阶段会运行单元测试
  3. 封装阶段包含两个并行运行的脚本:
    • 构建客户端
    • 导出服务器代码(主要用于提供信息)
  4. 部署阶段会将构建的客户端移动到 Web 服务器目录中。

我们可以看到,每个脚本都成功运行,如果其中一个脚本运行失败,则默认不会运行后面的脚本(但我们可以更改此行为):

如果我们打开脚本,可以查看日志并确定脚本运行失败的原因:

Running with gitlab-runner 10.4.0 (857480b6)
 on test runner (ab34a8c5)
Using Shell executor...
Running on gitlab-test...
Fetching changes...
Removing diff.xml
Removing full.xml
Removing index.html
Removing tests.html
HEAD is now at a5bf3e8 Merge branch '4-versiya-1-0' into 'master'
From http://gitlab.eduard.win/test/testProject
 * [new branch] 5-versiya-1-1 -> origin/5-versiya-1-1
 a5bf3e8..442a4db master -> origin/master
 d28295a..42a10aa preprod -> origin/preprod
 3ac4b21..7edf7f4 prod -> origin/prod
Checking out 442a4db1 as master...Skipping Git submodules setup$ csession ensemble "##class(isc.git.GitLab).loadDiff()"

[2018-03-06 13:58:19.188] Importing dir /home/gitlab-runner/builds/ab34a8c5/0/test/testProject/

[2018-03-06 13:58:19.188] Loading diff between a5bf3e8596d842c5cc3da7819409ed81e62c31e3 and 442a4db170aa58f2129e5889a4bb79261aa0cad0

[2018-03-06 13:58:19.192] Variable modified var=$lb("MyApp/Info.cls")

Load started on 03/06/2018 13:58:19 Loading file /home/gitlab-runner/builds/ab34a8c5/0/test/testProject/MyApp/Info.cls as udl Load finished successfully.

[2018-03-06 13:58:19.241] Variable items var="MyApp.Info.cls" var("MyApp.Info.cls")=""

Compilation started on 03/06/2018 13:58:19 with qualifiers 'cuk /checkuptodate=expandedonly' Compiling class MyApp.Info Compiling routine MyApp.Info.1 ERROR: MyApp.Info.cls(version+2) #1003: Expected space : '}' : Offset:14 [zversion+1^MyApp.Info.1] TEXT: quit, "1.0" } Detected 1 errors during compilation in 0.010s.

[2018-03-06 13:58:19.252] ERROR #5475: Error compiling routine: MyApp.Info.1. Errors: ERROR: MyApp.Info.cls(version+2) #1003: Expected space : '}' : Offset:14 [zversion+1^MyApp.Info.1] > ERROR #5030: An error occurred while compiling class 'MyApp.Info' ERROR: Job failed: exit status 1

编译错误导致脚本失败。

结论

  • GitLab 支持软件开发的所有主要阶段。
  • 持续交付可以帮助您自动执行软件构建、测试和部署任务。

后续内容

在下一篇文章中,我们将:

  • 安装 GitLab。
  • 将它连接到多个安装了 InterSystems 产品的环境。
  • 编写持续交付配置。

我们来探讨一下持续交付的运作方式。

首先,我们需要多个环境以及与之对应的分支。 代码进入此分支,并交付到目标环境:

环境分支交付有权提交的角色有权合并的角色
测试master自动开发者、所有者开发者、所有者
preprod预生产自动所有者
prod生产半自动(按下按钮进行交付)

所有者

作为示例,我们将使用 GitLab 流程开发一个新功能,并使用 GitLab CD 进行交付。

  1. 在功能分支中开发功能。
  2. 对功能分支进行审查并将其合并到 master 分支中。
  3. 一段时间(合并了多个功能)后,将 master 分支合并到 preprod 分支中
  4. 一段时间(用户测试等)后,将 preprod 分支合并到 prod 分支中

具体如下图所示:

  1. 开发和测试
    • 开发者将新功能的代码提交到单独的功能分支中
    • 功能稳定后,开发者将功能分支合并到 master 分支中
    • 来自 master 分支的代码被交付到测试环境,在其中进行加载和测试
  2. 交付到预生产环境
    • 开发者创建从 master 分支到 preprod 分支的合并请求
    • 仓库所有者在一段时间后批准合并请求
    • 来自 preprod 分支的代码被交付到预生产环境
  3. 交付到生产环境
    • 开发者创建从 preprod 分支到 prod 分支的合并请求
    • 仓库所有者在一段时间后批准合并请求
    • 仓库所有者按下“部署”按钮
    • 来自 prod 分支的代码被交付到生产环境

也可以用示意图形式表示此流程:

 

0
0 98
文章 Michael Lei · 九月 26, 2024 6m read

大家都搭建了测试环境。

有些人很幸运,可以在完全独立的环境中运行生产。

-- 佚名

.

在这一系列文章中,我想向大家介绍并探讨使用 InterSystems 技术和 GitLab 进行软件开发可以采用的几种方式。 我将介绍以下主题:

  • Git 101
  • Git 流程(开发流程)
  • GitLab 安装
  • GitLab 工作流
  • GitLab CI/CD
  • 包含容器的 CI/CD

第一部分将介绍现代软件开发的基础 – Git 版本控制系统和各种 Git 流程。

Git 101

虽然我们将主要探讨软件开发的概况以及 GitLab 如何帮助我们实现这一目标,但 Git,或者说 Git 设计中的几个基础的高级概念对于更好地理解后面的概念非常重要。

也就是说,Git 是基于这些概念的版本控制系统(还有更多概念,但这几个概念最为重要):

  • 非线性开发意味着,虽然我们的软件是从版本 1 到版本 2、再到版本 3 相继发布的,但实际上从版本 1 到版本 2 的升级是并行完成的 – 多名开发者会同时开发许多功能/错误修复。
  • 分布式开发意味着开发者独立于一个中央服务器或其他开发者,可以轻松地在自己的环境中进行开发。
  • 合并 – 基于前面提到的两个概念,我们会发现很多不同的版本同时存在,我们需要将它们统一成一个完整的状态。

我的意思不是说 Git 发明了这些概念。 Git 并没有发明这些概念, 而是使这些概念变得简单、流行,并加入了多个相关创新概念,也就是说,架构即代码/容器化改变了软件开发。

核心 git 术语

仓库是存储数据以及关于数据的元信息的项目。

  • “从物理层面来讲”,仓库是磁盘上的目录。
  • 仓库用于存储文件和目录。
  • 仓库还会存储每个文件的完整变更历史。

仓库可以:

  • 存储在您自己的计算机本地
  • 远程存储在远程服务器上

但从 git 的角度来看,本地仓库与远程仓库之间没有特殊的区别。

提交是仓库的固定状态。 很显然,如果每次提交都存储仓库的完整状态,我们的仓库很快就会变得非常大。 因此,提交会存储差异,也就是当前提交与其父提交之间的差异。

不同的提交可以具有不同数量的父提交:

  • 0 个 – 仓库中的第一个提交没有父提交。
  • 1 个 – 一切如常 - 我们的提交改变了仓库中的某些内容,就像在父提交期间一样
  • 2 个 – 当我们有两个不同的仓库状态时,我们可以将它们合并成一个新状态。 该状态和该提交就会有 2 个父提交。
  • >2 个 – 当我们将 2 个以上的不同仓库状态合并为一个新状态时,就会有 2 个以上的父提交。 这一概念与我们的讨论并没有特别大的关系,但它确实存在。

现在,对于父提交,每个与之不同的提交都被称为子提交。 每个父提交可以有任意数量的子提交。

分支是对提交的引用(或指针),如下图所示:

该图像显示的仓库具有两个提交(灰色圆圈),第二个圆圈是 master 分支的头部。 在我们添加更多提交后,仓库开始变成下图所示的状态:

这是最简单的情况。 我们的开发者一次负责处理一个更改。 但通常会有很多开发者同时负责处理不同的功能,我们需要使用提交树显示仓库中的变化。

提交树

我们从相同的起始状态开始。 仓库具有两个提交:

但现在,两名开发者在同时工作,为了避免相互干扰,他们在单独的分支中工作:

一段时间后,他们需要合并所做的更改,为此,他们创建了合并请求(也叫拉取请求), 顾名思义,该请求可将两个不同的仓库状态(本例中,我们要将 develop 分支合并到 master 分支中)合并为一个新状态。 接受相应审查并获得批准后,仓库状态如下图所示:

开发继续进行:

Git 101 - 总结

主要概念:

  • Git 是一个非线性的分布式版本控制系统。
  • 仓库用于存储数据以及关于数据的元信息。
  • 提交是仓库的固定状态。
  • 分支是对提交的引用。
  • 合并请求(也叫拉取请求)是将两个不同的仓库状态合并为一个新状态的请求。

如果您想了解更多关于 Git 的信息,可以阅读相关书籍

Git 流程

现在,读者已熟悉基本的 Git 术语和概念,我们来探讨一下如何使用 Git 管理软件生命周期的开发部分。很多实践(称为流程)介绍了使用 Git 的开发流程,但我们只会探讨其中两个:

  • GitHub 流程
  • GitLab 流程

GitHub 流程

GitHub 流程非常简单。 具体如下:

  1. 从仓库创建一个分支。
  2. 将更改提交到新分支
  3. 从您的分支发送一个拉取请求,其中包含您提议的更改,以发起讨论。
  4. 根据需要在您的分支上提交更多更改。 您的拉取请求将自动更新。
  5. 在分支准备好合并后,立即合并拉取请求。

我们需要遵守几条规则:

  • master 分支始终可部署(并且可正常运行!)
  • 不直接在 master 分支中进行开发
  • 在功能分支中进行开发
  • master 分支 == 生产* 环境**
  • 需要尽可能频繁地部署到生产环境

* 不要与“Ensemble 生产”混淆,这里的“生产”是指正式。

** 环境是配置好的代码运行位置,可以是服务器、虚拟机,甚至可以是容器。

如下图所示:

有关 GitHub 流程的更多信息,请参阅此处。 我们还提供了图解指南

GitHub 流程非常适合小型项目,如果您刚开始使用 Git 流程,可以尝试一下。 不过,GitHub 也会使用 GitHub 流程,因此也可以在大型项目中使用 GitHub 流程。

GitLab 流程

如果您还没有准备好立即部署到生产环境,GitLab 流程提供 GitHub 流程 + 环境。 具体做法是:在功能分支中进行开发(与上例相同),合并到 master 分支中(与上例相同),但这里有一个不同之处: master 分支仅等同于测试环境。 除此之外,还有链接到可能存在的各种其他环境的“环境分支”。

通常存在三个环境(可以根据需要创建更多环境):

  • 测试环境 == master 分支
  • 预生产环境 == preprod 分支
  • 生产环境 == prod 分支

进入其中一个环境分支的代码应立即移至相应的环境中,此流程可通过以下方式完成:

  • 自动(我们将在第 2 部分和第 3 部分探讨)
  • 半自动(与自动方式相同,唯一的区别是应按下按钮授权部署)
  • 手动

完整的流程是:

  1. 在功能分支中开发功能。
  2. 对功能分支进行审查并将其合并到 master 分支中。
  3. 一段时间(合并了多个功能)后,将 master 分支合并到 preprod 分支中
  4. 一段时间(用户测试等)后,将 preprod 分支合并到 prod 分支中
  5. 在我们进行合并和测试时,多个新功能已开发完毕并合并到 master 分支中,因此转到  3。

具体如下图所示:

有关 GitLab 流程的更多信息,请参阅此处

结论

  • Git是一个非线性的分布式版本控制系统。
  • Git 流程可用作软件开发周期的准则,有多种 Git 流程可供选择。

链接

讨论问题

  • 您使用 Git 流程吗? 使用哪一种?
  • 您为普通项目使用多少个环境?

后续内容

在接下来的部分中,我们将:

  • 安装 GitLab。
  • 探讨一些建议的调整。
  • 讨论 GitLab 工作流(不要与 GitLab 流程混淆)。

敬请关注。

0
0 129
文章 Qiao Peng · 三月 17, 2024 12m read

近来生成式大语言模型掀起了革命性的AI浪潮。生成式大语言模型是什么原理?我们怎么在业务中利用它?

一. 大语言模型的工作原理

生成式大语言模型是生成式人工智能底层的机器学习模型,是一种用于自然语言处理的深度学习模型。

人工智能、机器学习与大语言模型的关系如下图:

1.1 为什么我们称之为大语言模型?

大语言模型的“大”体现在多个方面:

  • 首先,模型尺寸巨大,尤其是它的参数数量。例如GPT3有1750亿的参数;
  • 其次,大语言模型是在巨大的算力基础上,基于海量语料进行训练的。例如Meta的Llama 2 的训练数据达到了两万亿个词(token);
  • 再次,大语言模型是为解决通用问题,而非特定问题构建的。

1.2 大语言模型是怎么训练的?

大语言模型是事先训练好的模型。

训练时,大语言模型基于各种语料 - 人类知识库(例如Wikipedia)、公共数据集、网络爬虫数据,让模型进行“填空”练习,并经过人工编辑和“校对” 训练出来的,需要成千上万的GPU建立集群进行训练。根据Meta的信息,其Llama 2 的训练数据达到了两万亿个token,上下文长度为4096,对话上也是使用100万人类标记的数据微调。

运行时,训练产生的大语言模型可以在小的多的硬件上运行。

1.3 大语言模型的机器学习算法

冰冻三尺,非一日之寒;滴水穿石,非一日之功。生成式大语言模型能够落地经历了相当漫长的技术积累与进步。

0
0 842
文章 Qiao Peng · 十二月 4, 2023 10m read

1. 通用RESTful业务服务和业务操作


InterSystems IRIS 提供了一组通用的RESTful 业务服务和业务操作类,用户无需开发自定义的业务服务和业务操作类,就可以直接向外提供RESTful服务和调用外部的RESTful API。

BS EnsLib.REST.GenericService 通用REST业务服务
BS EnsLib.REST.SAMLGenericService 检查SAML令牌的签名和时间戳的REST业务服务
BO EnsLib.REST.GenericOperation 通用REST业务操作
BO EnsLib.REST.GenericOperationInProc 用于透传模式的通用REST业务操作

2. 通用RESTful 消息

通用的RESTful 业务服务和业务操作类使用一个通用的RESTful消息类 - EnsLib.REST.GenericMessage,它是EnsLib.HTTP.GenericMessage的子类,二者数据结构都是

0
2 227
文章 Qiao Peng · 六月 11, 2023 7m read

数据平台一直在进化:从数据中心到数据中台,离散的数据资产得到进一步梳理和整合、按业务封装数据和操作数据的方法,并逐步提供了企业统一的访问、更新、检索、查询等数据服务。

然而市场上不乏听到数据平台的成功案例,却鲜见这些案例得到大规模推广。原因是什么呢?

一. 传统数据平台建设的挑战

传统数据平台的数据模型基于各自厂商的理解,缺乏统一行业数据模型和行业语义。可供参考的国内卫生信息数据元、数据集标准并非完整的行业语义,例如没有业务实体模型和数据元关系定义。传统的数据平台建设通常根据业务域,围绕数据应用需求组织数据。经常看到按业务域划分为CDR(临床数据中心)、ODR(运营数据中心)、RDR(科研数据中心)......  

这造成了几个挑战:

1. 按业务域、而非业务实体来划分数据,虽然方便相应的业务域数据分析,但跨业务域重叠的业务实体数据,例如患者,需要跨数据中心同步。这些同步由于数据模型上的差异,往往非全息拷贝。随着同步次数越多,跨数据中心的数据越失真,造成数据资产多源不统一、数据资产一致性问题和时效性问题。

2. 数据平台产品语义表达上参差不齐,业务用户依赖数据工程师对数据理解和操作,无论是统计分析还是机器学习,海量的实施工作无法满足业务敏捷性要求;

3. 数据平台及数据应用建设依赖单一厂商的能力,而建设成果,包括数据工具、分析指标和应用都无法跨数据平台复用。往往项目都在做低水平重复建设。

0
3 1006
文章 Claire Zheng · 十月 18, 2022 3m read

在美国各地,当需要实现大规模的应用集成时,医疗行业的领导者会使用InterSystems HealthShare Health Connect®。无论是为了连接电子病历,还是为了提升床边护理决策能力,无论是为了创新远程医疗和远程护理,还是为了业务增长,亦或是为未来做准备,InterSystems和Health Connect随时准备好帮助您和您的组织实现目标。我们在此提供几个InterSystems医疗行业的集成实例以作示范。

0
0 458
文章 Claire Zheng · 一月 20, 2021 5m read

我们不必等待SAM发布才开始规划和试用该API来监控IRIS实例。在以后的文章中,我将更深入地探讨可用的指标及其意义,并提供一些交互式仪表板的示例。首先,我将介绍一下相关背景和一些问题及答案。

IRIS(和Caché)一直在收集自身及其运行平台的数十个指标。收集这些指标来监控Caché和IRIS的方法向来有很多。我发现,很少有安装软件使用IRIS和Caché的内置解决方案。譬如,History Monitor作为性能和系统使用指标的历史数据库,已经推出很长时间了,但它没有简便方法可实时显示这些指标和仪表系统。

IRIS平台解决方案(以及整个业界)正在从仅在一些本地实例上运行的单体式应用程序过渡到“随处”部署的分布式解决方案。在许多用例中,原有的IRIS监控方案并不适用于这些新的模式。InterSystems没有做重复工作,而是将目光投向当前流行的、经过验证的监控和告警开源解决方案。

0
0 397