本教程介绍了如何使用最小底层协议 (MLLP) 通过 TCP/IP 连接传输 HL7v2 消息。如需要求证明者将 MLLP 映像进行签名,请参考使用已签名的 MLLP 映像通过 TCP/IP 连接传输 HL7v2 消息中的步骤。
本教程介绍了如何在以下环境中运行在 GitHub 中托管的开源 MLLP 适配器:
- 本地
- 在 GKE 上的容器中,使用 Cloud VPN。
- 在 GKE 上的容器中,不使用 Cloud VPN。
目标
完成本教程后,您将了解如何执行以下任务:
- 使用 Cloud Healthcare API 在本地构建并配置 MLLP 适配器,并测试如何将 HL7v2 消息发送到 HL7v2 存储区。
- 将 MLLP 适配器部署到 GKE 并从 Compute Engine 虚拟机实例发送 HL7v2 消息。
- 配置 VPN,保护“本地”实例与 MLLP 适配器之间的连接,并从“本地”实例发送 HL7v2 消息。
费用
在本文档中,您将使用 Google Cloud 的以下收费组件:
- Cloud Healthcare API
- Google Kubernetes Engine
- Compute Engine
- Cloud VPN
- Pub/Sub
您可使用价格计算器根据您的预计使用情况来估算费用。
须知事项
在开始学习本教程之前,请查看 MLLP 和 Google Cloud MLLP 适配器,熟悉有关最小底层协议 (MLLP) 的概念性文档。该概念性文档简要介绍了 MLLP,医疗保健系统如何通过 MLLP 连接向 Cloud Healthcare API 发送和接收消息,以及 MLLP 安全的基础知识。
在设置 MLLP 适配器之前,您必须选择或创建一个 Google Cloud 项目,并通过完成以下步骤来启用所需的 API:
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Cloud Healthcare API, Google Kubernetes Engine, Container Registry, and Pub/Sub APIs.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Cloud Healthcare API, Google Kubernetes Engine, Container Registry, and Pub/Sub APIs.
- 稍作等待,让 Kubernetes Engine API 和相关服务完成启用过程。 此过程可能耗时几分钟。
选择 shell
要完成本教程,您可以使用 Cloud Shell 或本地 shell。
Cloud Shell 是一种 shell 环境,用于管理托管在 Google Cloud 上的资源。Cloud Shell 预装了 gcloud CLI 和 kubectl
工具。gcloud CLI 提供了 Google Cloud 的主要命令行界面。kubectl
提供了用于针对 GKE 集群运行命令的命令行界面。
如果您更喜欢使用本地 shell,则必须安装 gcloud CLI。
如需打开 Cloud Shell 或配置本地 shell,请完成以下步骤:
Cloud Shell
如需启动 Cloud Shell,请完成以下步骤:
进入 Google Cloud 控制台。
在控制台的右上角,点击激活 Google Cloud Shell 按钮:
控制台底部的框中随即打开一个 Cloud Shell 会话。您可以使用此 shell 运行 gcloud
和 kubectl
命令。
本地 Shell
如需安装 gcloud CLI 和 kubectl
工具,请完成以下步骤:
- 安装并初始化 Google Cloud CLI。
如果只是在本地测试适配器,则无需完成任何其他步骤,可以继续创建数据集。如果要将适配器部署到 GKE,请通过运行以下命令安装
kubectl
命令行工具:gcloud components install kubectl
创建数据集
如果尚未创建 Cloud Healthcare API 数据集,请按照以下步骤创建数据集:
控制台
- 在 Google Cloud 控制台中,转到数据集页面。
- 点击创建数据集。
-
在名称字段中,输入数据集的标识符。数据集 ID 必须符合以下条件:
- 位置中的唯一 ID
- 由 1-256 个字符组成的 Unicode 字符串,由以下各项组成:
- 数字
- 字母
- 下划线
- 短划线
- 英文句点
-
在位置类型部分,选择以下某一类型的位置:
- 单区域:数据集永久驻留在一个 Google Cloud 区域中。选择此类型后,在单区域字段中输入或选择位置。
- 多区域:数据集永久驻留在跨多个 Google Cloud 区域的位置中。选择此类型后,在多区域字段中输入或选择多区域位置。
- 点击创建。
新数据集将显示在数据集列表中。
gcloud
要创建数据集,请运行 gcloud healthcare datasets create
命令:
gcloud healthcare datasets create DATASET_ID \ --location=LOCATION
如果请求成功,命令将返回以下输出:
Create request issued for: [DATASET_ID] Waiting for operation [OPERATION_ID] to complete...done. Created dataset [DATASET_ID].
创建 Pub/Sub 主题和订阅
要在创建或提取消息时收到通知,您需要使用 HL7v2 存储区配置 Pub/Sub 主题。如需了解详情,请参阅配置 Pub/Sub 通知。
如需创建主题,请完成以下步骤:
控制台
进入 Google Cloud 控制台中的 Pub/Sub 主题页面。
点击创建主题。
在主题名称中输入 URI:
projects/PROJECT_ID/topics/TOPIC_NAME
其中 PROJECT_ID 是您的 Google Cloud 项目 ID。
点击创建。
gcloud
要创建主题,请运行 gcloud pubsub topics create
命令:
gcloud pubsub topics create projects/PROJECT_ID/topics/TOPIC_NAME
如果请求成功,命令将返回以下输出:
Created topic [projects/PROJECT_ID/topics/TOPIC_NAME].
如需创建订阅,请完成以下步骤。
控制台
进入 Google Cloud 控制台中的 Pub/Sub 主题页面。
点击项目的主题。
点击创建订阅。
输入订阅名称:
projects/PROJECT_ID/subscriptions/SUBSCRIPTION_NAME
将传送类型的设置保留为拉取,然后点击创建。
gcloud
要创建订阅,请运行 gcloud pubsub subscriptions create
命令:
gcloud pubsub subscriptions create SUBSCRIPTION_NAME \ --topic=projects/PROJECT_ID/topics/TOPIC_NAME
如果请求成功,命令将返回以下输出:
Created subscription [projects/PROJECT_ID/subscriptions/SUBSCRIPTION_NAME].
创建使用 Pub/Sub 主题配置的 HL7v2 存储区
创建 HL7v2 存储区,然后使用 Pub/Sub 主题进行配置。要创建 HL7v2 存储区,必须已创建数据集。在本教程中,请对 HL7v2 存储区和 Pub/Sub 主题使用同一项目。
要创建使用 Pub/Sub 主题配置的 HL7v2 存储区,请完成以下步骤:
curl
curl -X POST \ --data "{ 'notificationConfigs': [ { 'pubsubTopic': 'projects/PROJECT_ID/topics/PUBSUB_TOPIC', 'filter': '' } ] }" \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores?hl7V2StoreId=HL7V2_STORE_ID"
如果请求成功,服务器将以 JSON 格式返回响应:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID", "notificationConfigs": [ { "pubsubTopic": "projects/PROJECT_ID/topics/PUBSUB_TOPIC" } ] }
PowerShell
$cred = gcloud auth application-default print-access-token $headers = @{ Authorization = "Bearer $cred" } Invoke-WebRequest ` -Method Post ` -Headers $headers ` -ContentType: "application/json; charset=utf-8" ` -Body "{ 'notificationConfigs': [ { 'pubsubTopic': 'projects/PROJECT_ID/topics/PUBSUB_TOPIC', 'filter': '' } ] }" ` -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores?hl7V2StoreId=HL7V2_STORE_ID" | Select-Object -Expand Content
如果请求成功,服务器将以 JSON 格式返回响应:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID", "notificationConfigs": [ { "pubsubTopic": "projects/PROJECT_ID/topics/PUBSUB_TOPIC" } ] }
配置 Pub/Sub 权限
要在创建或提取 HL7v2 消息时向 Pub/Sub 发送通知,需要在 Cloud Healthcare API 上配置 Pub/Sub 权限。此步骤需要针对每个项目执行一次。
要将所需的 pubsub.publisher
角色添加到项目的服务账号,请完成以下步骤:
控制台
gcloud
如需添加服务账号权限,请运行 gcloud projects add-iam-policy-binding
命令。如需了解如何查找 PROJECT_ID 和 PROJECT_NUMBER,请参阅识别项目。
gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-healthcare.iam.gserviceaccount.com \ --role=roles/pubsub.publisher
拉取预构建的 Docker 映像
MLLP 适配器是暂存在 Container Registry 内的预构建 Docker 映像中的容器化应用。
要拉取映像的最新版本,请运行以下命令:
docker pull gcr.io/cloud-healthcare-containers/mllp-adapter:latest
在本地测试 MLLP 适配器
在本地测试适配器时,可以将其配置为以接收者、发布商或两者的身份运行。接收者和发布商配置存在以下主要区别:
- 当适配器作为接收者运行时,会接收来自外部来源的 HL7v2 消息,并调用
messages.ingest
将消息注入到 HL7v2 存储区中,从而创建 Pub/Sub 通知。该通知会发送给已订阅 HL7v2 存储区的 Pub/Sub 主题的应用。 - 当适配器以发布商身份运行时,它会侦听使用
messages.create
或messages.ingest
在 HL7v2 存储区中创建或提取的 HL7v2 消息。创建消息后,系统会将 Pub/Sub 通知发送到适配器,然后适配器将消息发布到外部接收者。
验证可以在本地机器上运行 MLLP 适配器后,可以继续阅读将 MLLP 适配器部署到 Google Kubernetes Engine 中的下一部分。
以接收者的身份测试 MLLP 适配器
当适配器收到来自外部来源(例如护理中心)的 HL7v2 消息时,适配器会调用 messages.ingest
并将 HL7v2 消息提取到配置的 HL7v2 存储区中。您可以在适配器的源代码中观察到这一点。
要在本地将适配器作为接收者进行测试,请完成以下步骤:
在拉取预构建 Docker 映像的机器上,运行以下命令:
docker run \ --network=host \ -v ~/.config:/root/.config \ gcr.io/cloud-healthcare-containers/mllp-adapter \ /usr/mllp_adapter/mllp_adapter \ --hl7_v2_project_id=PROJECT_ID \ --hl7_v2_location_id=LOCATION \ --hl7_v2_dataset_id=DATASET_ID \ --hl7_v2_store_id=HL7V2_STORE_ID \ --export_stats=false \ --receiver_ip=0.0.0.0 \ --port=2575 \ --api_addr_prefix=https://healthcare.googleapis.com:443/v1 \ --logtostderr
其中:
- PROJECT_ID 是包含 HL7v2 存储区的 Google Cloud 项目的 ID。
- LOCATION 是 HL7v2 存储区所在的区域。
- DATASET_ID 是 HL7v2 存储区的父数据集的 ID。
- HL7V2_STORE_ID 是您要向其发送 HL7v2 消息的 HL7v2 存储区 ID。
运行上一个命令后,适配器会打印类似于以下内容的消息,并开始在本地机器上(IP 地址 127.0.0.1,端口 2575)运行:
I0000 00:00:00.000000 1 healthapiclient.go:171] Dialing connection to https://healthcare.googleapis.com:443/v1 I0000 00:00:00.000000 1 mllp_adapter.go:89] Either --pubsub_project_id or --pubsub_subscription is not provided, notifications of the new messages are not read and no outgoing messages will be sent to the target MLLP address.
如果您遇到任何错误,请按照以下问题排查步骤操作:
如果您使用的是 Mac OS,并且上一个命令失败并出现
Connection refused
错误,请参阅在本地运行时连接遭拒错误。如果上一条命令失败并显示
healthapiclient.NewHL7V2Client: oauth2google.DefaultTokenSource: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
错误,请参阅在本地运行时出现could not find default credentials
错误。如果您遇到任何其他身份验证错误,请参阅身份验证错误。
要在适配器作为前台进程运行时继续进行测试,请在本地机器上打开另一个终端。
在新终端中,要安装 Netcat,请运行以下命令:
sudo apt install netcat
下载
hl7v2-mllp-sample.txt
文件并将其保存到本地机器。要将 HL7v2 消息发送到适配器,请在下载该文件的目录中运行以下命令。MLLP 适配器正在侦听本地主机的端口 2575。该命令通过 MLLP 适配器将消息发送到您的 HL7v2 存储区。
Linux
echo -n -e "\x0b$(cat hl7v2-mllp-sample.txt)\x1c\x0d" | nc -q1 localhost 2575 | less
如果已将消息成功提取到 HL7v2 存储区中,则该命令将返回以下输出:
^KMSH|^~\&|TO_APP|TO_FACILITY|FROM_APP|FROM_FACILITY|19700101010000||ACK|c507a97e-438d-44b0-b236-ea95e5ecbbfb|P|2.5^MMSA|AA|20150503223000^\
此输出表明 HL7v2 存储区以
AA
(Application Accept
) 响应类型进行响应,这意味着消息已通过验证并成功提取。您还可以通过打开运行适配器的终端来验证消息是否已成功发送。输出应类似于以下示例:
I0000 00:00:00.000000 1 healthapiclient.go:171] Dialing connection to https://healthcare.googleapis.com:443/v1 I0000 00:00:00.000000 1 mllp_adapter.go:89] Either --pubsub_project_id or --pubsub_subscription is not provided, notifications of the new messages are not read and no outgoing messages will be sent to the target MLLP address. I0213 00:00:00.000000 1 healthapiclient.go:190] Sending message of size 319. I0213 00:00:00.000000 1 healthapiclient.go:223] Message was successfully sent.
该消息存储在您的 HL7v2 存储区中,因此您可以调用
messages.list
来查看该消息:curl
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages"
如果请求成功,服务器将在资源路径中返回消息的 ID:
{ "hl7V2Messages": [ { "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID" } ] }
PowerShell
$cred = gcloud auth application-default print-access-token $headers = @{ Authorization = "Bearer $cred" } Invoke-WebRequest ` -Method Get ` -Headers $headers ` -ContentType: "application/json; charset=utf-8" ` -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages" | Select-Object -Expand Content
如果请求成功,服务器将在资源路径中返回消息的 ID:
{ "hl7V2Messages": [ { "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID" } ] }
以发布商的身份在本地测试 MLLP 适配器
以发布商身份测试适配器时,可以通过调用 messages.create
或 messages.ingest
,并以二进制数据形式提供消息文件来创建消息。
适配器会自动确认通过 messages.create
和 messages.ingest
发送的 Pub/Sub 消息。
适配器会在成功提取并发送 Pub/Sub 消息时通知您。适配器是 Pub/Sub 订阅者,因此它会自动确认这些消息。因此,它们会从您使用适配器配置的 Pub/Sub 订阅的消息队列中移除。
要从 Pub/Sub 订阅中拉取并单独验证消息是否已发布,您需要再创建一个分配给您之前创建的主题的 Pub/Sub 订阅。适配器不会自动确认发送到第二个订阅的消息,并保留这些消息供您拉取。
要创建分配给您之前创建的主题的第二个 Pub/Sub 订阅,请完成以下步骤:
控制台
进入 Google Cloud 控制台中的 Pub/Sub 主题页面。
点击项目的主题。这是您用于创建初始订阅的主题。
点击创建订阅。
输入订阅名称:
projects/PROJECT_ID/subscriptions/SECOND_SUBSCRIPTION_NAME
将传送类型设置保留为拉取。
点击创建。
gcloud
要创建分配给您之前创建的主题的第二个 Pub/Sub 订阅,请运行 gcloud pubsub subscriptions create
命令:
gcloud pubsub subscriptions create SECOND_SUBSCRIPTION_NAME --topic=projects/PROJECT_ID/topics/TOPIC_NAME
如果请求成功,命令将返回以下输出:
Created subscription [projects/PROJECT_ID/subscriptions/SECOND_SUBSCRIPTION_NAME].
要以发布商身份在本地测试适配器,请在拉取预构建 Docker 映像的机器上完成以下步骤:
安装 Netcat:
sudo apt install netcat
下载
hl7v2-mllp-ack-sample.txt
文件并将其保存到本地机器。该文件包含适配器在尝试发布消息时要求作为响应的 ACK 消息。如需允许 Netcat 监听端口 2525 上的传入连接,请在下载文件的目录中运行以下命令。
Linux
echo -n -e "\x0b$(cat hl7v2-mllp-ack-sample.txt)\x1c\x0d" | nc -q1 -lv -p 2525 | less
启动 Netcat 后,将显示类似于以下示例的输出消息:
listening on [any] 2525 ...
Netcat 作为前台进程运行,因此要继续测试,请在本地机器上打开另一个终端。
要启动适配器,请在新终端中运行以下命令:
docker run \ --network=host \ gcr.io/cloud-healthcare-containers/mllp-adapter \ /usr/mllp_adapter/mllp_adapter \ --hl7_v2_project_id=PROJECT_ID \ --hl7_v2_location_id=LOCATION \ --hl7_v2_dataset_id=DATASET_ID \ --hl7_v2_store_id=HL7V2_STORE_ID \ --export_stats=false \ --receiver_ip=127.0.0.1 --port 2575 \ --mllp_addr=127.0.0.1:2525 \ --pubsub_project_id=PROJECT_ID \ --pubsub_subscription=PUBSUB_SUBSCRIPTION \ --api_addr_prefix=https://healthcare.googleapis.com:443/v1 \ --logtostderr
其中:
- PROJECT_ID 是包含 HL7v2 存储区的 Google Cloud 项目的 ID。
- LOCATION 是 HL7v2 存储区所在的区域。
- DATASET_ID 是 HL7v2 存储区的父数据集的 ID。
- HL7V2_STORE_ID 是您要向其发送 HL7v2 消息的 HL7v2 存储区 ID。
- PROJECT_ID 是包含 Pub/Sub 主题的 Google Cloud 项目的 ID。
- PUBSUB_SUBSCRIPTION 是您创建的与 Pub/Sub 主题关联的第一个订阅的名称。适配器会使用来自此订阅的消息并自动确认消息,因此要查看发布到主题的消息,必须从之前创建的第二个订阅中拉取消息。
运行上一个命令后,适配器会开始在本地计算机上(IP 地址 127.0.0.1,端口 2575)运行:
如果您遇到任何错误,请按照以下问题排查步骤操作:
如果您使用的是 Mac OS,并且上一个命令失败并出现
Connection refused
错误,请参阅在本地运行时连接遭拒错误。如果上一条命令失败并显示
healthapiclient.NewHL7V2Client: oauth2google.DefaultTokenSource: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
错误,请参阅在本地运行时出现could not find default credentials
错误。如果您遇到任何其他身份验证错误,请参阅身份验证错误。
适配器作为前台进程运行,因此要继续测试,请在本地机器上打开另一个终端。
下载
hl7v2-sample.json
文件并将其保存到本地机器。在下载该文件的目录中,调用messages.create
方法以在 HL7v2 存储区中创建消息:curl
要创建 HL7v2 消息,请发出
POST
请求并指定以下信息:- 父数据集的名称
- HL7v2 存储区的名称
- 一条消息
- 访问令牌
以下示例显示了使用
curl
的POST
请求以及名为hl7v2-sample.json
的示例 JSON 文件。curl -X POST \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ --data-binary @hl7v2-sample.json \ "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages"
如果请求成功,服务器将以 JSON 格式返回响应:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID", "data": "TVNIfF5+XCZ8QXxTRU5EX0ZBQ0lMSVRZfEF8QXwyMDE4MDEwMTAwMDAwMHx8VFlQRV5BfDIwMTgwMTAxMDAwMDAwfFR8MC4wfHx8QUF8fDAwfEFTQ0lJDUVWTnxBMDB8MjAxODAxMDEwNDAwMDANUElEfHwxNAExMTFeXl5eTVJOfDExMTExMTExXl5eXk1STn4xMTExMTExMTExXl5eXk9SR05NQlI=", "sendFacility": "SEND_FACILITY", "sendTime": "2018-01-01T00:00:00Z", "messageType": "TYPE", "createTime": "1970-01-01T00:00:00Z", "patientIds": [ { "value": "14\u0001111", "type": "MRN" }, { "value": "11111111", "type": "MRN" }, { "value": "1111111111", "type": "ORGNMBR" } ] }
PowerShell
要创建 HL7v2 消息,请发出
POST
请求并指定以下信息:- 父数据集的名称
- HL7v2 存储区的名称
- 一条消息
- 访问令牌
以下示例显示了使用 Windows PowerShell 的
POST
请求以及名为hl7v2-sample.json
的示例 JSON 文件。$cred = gcloud auth application-default print-access-token $headers = @{ Authorization = "Bearer $cred" } Invoke-WebRequest ` -Method Post ` -Headers $headers ` -ContentType: "application/json; charset=utf-8" ` -InFile hl7v2-sample.json ` -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages" | Select-Object -Expand Content
如果请求成功,服务器将以 JSON 格式返回响应:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID", "data": "TVNIfF5+XCZ8QXxTRU5EX0ZBQ0lMSVRZfEF8QXwyMDE4MDEwMTAwMDAwMHx8VFlQRV5BfDIwMTgwMTAxMDAwMDAwfFR8MC4wfHx8QUF8fDAwfEFTQ0lJDUVWTnxBMDB8MjAxODAxMDEwNDAwMDANUElEfHwxNAExMTFeXl5eTVJOfDExMTExMTExXl5eXk1STn4xMTExMTExMTExXl5eXk9SR05NQlI=", "sendFacility": "SEND_FACILITY", "sendTime": "2018-01-01T00:00:00Z", "messageType": "TYPE", "createTime": "1970-01-01T00:00:00Z", "patientIds": [ { "value": "14\u0001111", "type": "MRN" }, { "value": "11111111", "type": "MRN" }, { "value": "1111111111", "type": "ORGNMBR" } ] }
创建消息后,MLLP 适配器将返回以下响应:
I0214 00:00:00.000000 1 healthapiclient.go:266] Started to fetch message. I0214 00:00:00.000000 1 healthapiclient.go:283] Message was successfully fetched.
在运行 Netcat 的终端中,将显示类似于以下示例的输出。此输出表明消息已发布:
connect to [127.0.0.1] from localhost [127.0.0.1] 39522 ^KMSH|^~\&|A|SEND_FACILITY|A|A|20180101000000||TYPE^A|20180101000000|T|0.0|||AA||00|ASCII^MEVN|A00|20180101040000^MPID||14^A111^^^^MRN|11111111^^^^MRN~1111111111^^^^ORGNMBR^\
这对应于您在创建消息时收到的响应的
data
字段中的值。它与hl7v2-sample.json
文件中的data
值相同。要查看适配器发布到 Pub/Sub 主题的消息,请在您创建的第二个 Pub/Sub 订阅上运行
gcloud pubsub subscriptions pull
命令:gcloud pubsub subscriptions pull --auto-ack SECOND_SUBSCRIPTION
该命令会返回有关所创建 HL7v2 消息的以下输出。请注意
ATTRIBUTES
列中的publish=true
值,该值表示消息已发布到 Pub/Sub:┌-----------------------------------------------------------------------------------------------------------------|-----------------|---------------┐ | DATA | MESSAGE_ID | ATTRIBUTES | ├-----------------------------------------------------------------------------------------------------------------|-----------------|---------------| | projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/HL7V2_MESSAGE_ID | 123456789012345 | msgType=ADT | | | | publish=true | └-----------------------------------------------------------------------------------------------------------------|-----------------|---------------┘
将消息发布到不同的外部接收者
您可以使用多个 Pub/Sub 主题配置 HL7v2 存储区,并使用过滤器向不同的 Pub/Sub 主题发送通知。然后,可以为每个 Pub/Sub 主题运行 MLLP 适配器,将消息发布到其他外部接收者。
要使用多个 Pub/Sub 主题配置 HL7v2 存储区,并为每个主题配置一个过滤器,请完成以下步骤:
创建两个 Pub/Sub 主题,并为每个主题创建一个订阅。如需了解详情,请参阅创建 Pub/Sub 主题和订阅。
运行以下命令:
curl
curl -X PATCH \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ --data "{ 'notificationConfigs': [ { 'pubsubTopic': 'projects/PROJECT_ID/topics/PUBSUB_TOPIC', 'filter' : 'sendFacility=\"SEND_FACILITY_1\"' }, { 'pubsubTopic': 'projects/PROJECT_ID/topics/SECOND_PUBSUB_TOPIC', 'filter': 'sendFacility=\"SEND_FACILITY_2\"' } ] }" "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID?updateMask=notificationConfigs"
如果请求成功,服务器将以 JSON 格式返回响应:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID", "notificationConfigs": [ { "pubsubTopic": "projects/PROJECT_ID/topics/PUBSUB_TOPIC", "filter": "sendFacility=\"SEND_FACILITY_1\"" }, { "pubsubTopic": "projects/PROJECT_ID/topics/SECOND_PUBSUB_TOPIC", "filter": "sendFacility=\"SEND_FACILITY_2\"" } ] }
PowerShell
$cred = gcloud auth application-default print-access-token $headers = @{ Authorization = "Bearer $cred" } Invoke-WebRequest ` -Method Patch ` -Headers $headers ` -ContentType: "application/json; charset=utf-8" ` -Body "{ 'notificationConfigs': [ { 'pubsubTopic' : 'projects/PROJECT_ID/topics/PUBSUB_TOPIC', 'filter': 'sendFacility=\"SEND_FACILITY_1\"' }, { 'pubsubTopic' : 'projects/PROJECT_ID/topics/SECOND_PUBSUB_TOPIC', 'filter' : 'sendFacility=\"SEND_FACILITY_2\"' } ] }" ` -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores?hl7V2StoreId=HL7V2_STORE_ID?updateMask=notificationConfigs" | Select-Object -Expand Content
如果请求成功,服务器将以 JSON 格式返回响应:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID", "notificationConfigs": [ { "pubsubTopic": "projects/PROJECT_ID/topics/PUBSUB_TOPIC", "filter": "sendFacility=\"SEND_FACILITY_1\"" }, { "pubsubTopic": "projects/PROJECT_ID/topics/SECOND_PUBSUB_TOPIC", "filter": "sendFacility=\"SEND_FACILITY_2\"" } ] }
测试消息路由
要测试邮件路由,请完成以下部分中的步骤。
配置并启动第一个接收者和适配器
要配置并启动第一个接收者和适配器,请完成以下步骤:
在拉取预构建 Docker 映像的机器上,运行以下命令以安装 Netcat:
sudo apt install netcat
下载
hl7v2-mllp-ack-sample.txt
(如果尚未下载)。该文件包含一条ACK
消息,由适配器在尝试发布消息时用作响应。要为第一个接收者设置端口 2525,请运行以下命令:
Linux
echo -n -e "\x0b$(cat hl7v2-mllp-ack-sample.txt)\x1c\x0d" | nc -q1 -lv -p 2525 | less
当 Netcat 进程启动时,将显示以下输出:
listening on [any] 2525 ...
要启动第一个适配器,请在新终端中运行以下命令:
docker run \ --network=host \ gcr.io/cloud-healthcare-containers/mllp-adapter \ /usr/mllp_adapter/mllp_adapter \ --hl7_v2_project_id=PROJECT_ID \ --hl7_v2_location_id=LOCATION \ --hl7_v2_dataset_id=DATASET_ID \ --hl7_v2_store_id=HL7V2_STORE_ID \ --export_stats=false \ --receiver_ip=127.0.0.1 --port 2575 \ --mllp_addr=127.0.0.1:2525 \ --pubsub_project_id=PROJECT_ID \ --pubsub_subscription=PUBSUB_SUBSCRIPTION \ --api_addr_prefix=https://healthcare.googleapis.com:443/v1 \ --logtostderr
其中:
- PROJECT_ID 是包含 HL7v2 存储区的 Google Cloud 项目的 ID。
- LOCATION 是 HL7v2 存储区所在的区域。
- DATASET_ID 是 HL7v2 存储区的父数据集的 ID。
- HL7V2_STORE_ID 是您要向其发送 HL7v2 消息的 HL7v2 存储区 ID。
- PROJECT_ID 是包含 Pub/Sub 主题的 Google Cloud 项目的 ID。
- PUBSUB_SUBSCRIPTION 是您创建的、与第一个 Pub/Sub 主题关联的第一个订阅的名称。适配器会使用来自此订阅的消息,并自动确认消息。
运行此命令后,适配器开始在本地机器 (127.0.0.1:2575) 上运行。它会向端口 2525 上的第一个外部接收者发布新消息。
配置并启动第二个接收者和适配器
要配置并启动第二个接收者和适配器,请完成以下步骤:
在拉取预构建 Docker 映像的机器上,运行以下命令以安装 Netcat:
sudo apt install netcat
下载
hl7v2-mllp-ack-sample.txt
(如果尚未下载)。该文件包含一条ACK
消息,由适配器在尝试发布消息时用作响应。要为第二个接收者设置端口 2526,请运行以下命令。
Linux
echo -n -e "\x0b$(cat hl7v2-mllp-ack-sample.txt)\x1c\x0d" | nc -q1 -lv -p 2526 | less
当 Netcat 进程启动时,将显示以下输出:
listening on [any] 2526 ...
要启动第二个适配器,请在新终端中运行以下命令:
docker run \ --network=host \ gcr.io/cloud-healthcare-containers/mllp-adapter \ /usr/mllp_adapter/mllp_adapter \ --hl7_v2_project_id=PROJECT_ID \ --hl7_v2_location_id=LOCATION \ --hl7_v2_dataset_id=DATASET_ID \ --hl7_v2_store_id=HL7V2_STORE_ID \ --export_stats=false \ --receiver_ip=127.0.0.1 --port 2576 \ --mllp_addr=127.0.0.1:2526 \ --pubsub_project_id=PROJECT_ID \ --pubsub_subscription=SECOND_PUBSUB_SUBSCRIPTION \ --api_addr_prefix=https://healthcare.googleapis.com:443/v1 \ --logtostderr
其中:
- PROJECT_ID 是包含 HL7v2 存储区的 Google Cloud 项目的 ID。
- LOCATION 是 HL7v2 存储区所在的区域。
- DATASET_ID 是 HL7v2 存储区的父数据集的 ID。
- HL7V2_STORE_ID 是您要向其发送 HL7v2 消息的 HL7v2 存储区 ID。
- PROJECT_ID 是包含 Pub/Sub 主题的 Google Cloud 项目的 ID。
- SECOND_PUBSUB_SUBSCRIPTION 是您创建的、与第二个 Pub/Sub 主题关联的第二个订阅的名称。适配器会使用来自此订阅的消息,并自动确认消息。
运行此命令后,适配器开始在本地机器 (127.0.0.1:2576) 上运行。它会将新消息发布到端口 2526 上的第二个外部接收者。
将消息发布到第一个接收者
要创建只会发布给第一个外部接收者的消息,请完成以下步骤:
在您下载
hl7v2-sample1.json
的目录中,调用messages.create
方法以在 HL7v2 存储区中创建消息:curl
要创建 HL7v2 消息,请发出
POST
请求并指定以下信息:- 父数据集的名称
- HL7v2 存储区的名称
- 一条消息
- 访问令牌
以下示例显示了使用
curl
的POST
请求以及示例 JSON 文件hl7v2-sample1.json
。curl -X POST \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ --data-binary @hl7v2-sample1.json \ "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages"
如果请求成功,服务器将以 JSON 格式返回响应:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID", "data": "TVNIfF5+XCZ8QXxTRU5EX0ZBQ0lMSVRZXzF8QXxBfDIwMTgwMTAxMDAwMDAwfHxUWVBFXkF8MjAxODAxMDEwMDAwMDB8VHwwLjB8fHxBQXx8MDB8QVNDSUkNRVZOfEEwMHwyMDE4MDEwMTA0MDAwMA1QSUR8fDE0ATExMV5eXl5NUk58MTExMTExMTFeXl5eTVJOfjExMTExMTExMTFeXl5eT1JHTk1CUg==", "sendFacility": "SEND_FACILITY_1", "sendTime": "2018-01-01T00:00:00Z", "messageType": "TYPE", "createTime": "1970-01-01T00:00:00Z", "patientIds": [ { "value": "14\u0001111", "type": "MRN" }, { "value": "11111111", "type": "MRN" }, { "value": "1111111111", "type": "ORGNMBR" } ] }
PowerShell
要创建 HL7v2 消息,请发出
POST
请求并指定以下信息:- 父数据集的名称
- HL7v2 存储区的名称
- 一条消息
- 访问令牌
以下示例显示了使用 Windows PowerShell 的
POST
请求以及名为hl7v2-sample1.json
的示例 JSON 文件。$cred = gcloud auth application-default print-access-token $headers = @{ Authorization = "Bearer $cred" } Invoke-WebRequest ` -Method Post ` -Headers $headers ` -ContentType: "application/json; charset=utf-8" ` -InFile hl7v2-sample1.json ` -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages" | Select-Object -Expand Content
如果请求成功,服务器将以 JSON 格式返回响应:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID", "data": "TVNIfF5+XCZ8QXxTRU5EX0ZBQ0lMSVRZXzF8QXxBfDIwMTgwMTAxMDAwMDAwfHxUWVBFXkF8MjAxODAxMDEwMDAwMDB8VHwwLjB8fHxBQXx8MDB8QVNDSUkNRVZOfEEwMHwyMDE4MDEwMTA0MDAwMA1QSUR8fDE0ATExMV5eXl5NUk58MTExMTExMTFeXl5eTVJOfjExMTExMTExMTFeXl5eT1JHTk1CUg==", "sendFacility": "SEND_FACILITY_1", "sendTime": "2018-01-01T00:00:00Z", "messageType": "TYPE", "createTime": "1970-01-01T00:00:00Z", "patientIds": [ { "value": "14\u0001111", "type": "MRN" }, { "value": "11111111", "type": "MRN" }, { "value": "1111111111", "type": "ORGNMBR" } ] }
在此响应中,
sendFacility
设置为SEND_FACILITY_1
,因此 Pub/Sub 通知仅会发送到第一个 Pub/Sub 主题。创建消息后,第一个 MLLP 适配器将返回以下响应:I0214 00:00:00.000000 1 healthapiclient.go:266] Started to fetch message. I0214 00:00:00.000000 1 healthapiclient.go:283] Message was successfully fetched.
第二个 MLLP 适配器不会返回任何响应,因为没有向第二个 Pub/Sub 主题发送任何通知。
在运行第一个 Netcat 进程的终端中,将显示以下输出。此输出表明消息已发布。
connect to [127.0.0.1] from localhost [127.0.0.1] 39522 ^KMSH|^~\&|A|SEND_FACILITY_1|A|A|20180101000000||TYPE^A|20180101000000|T|0.0|||AA||00|ASCII^MEVN|A00|20180101040000^MPID||14^A111^^^^MRN|11111111^^^^MRN~1111111111^^^^ORGNMBR^\
此输出对应于您在创建消息时收到的响应的
data
字段中的值。它与hl7v2-sample1.json
文件中的data
值相同。
将消息发布到第二个接收者
要创建只会发布给第二个外部接收者的消息,请完成以下步骤:
在本地机器上打开一个新终端。
要创建只会发布给第二个外部接收者的消息,请下载
hl7v2-sample2.json
。在您下载
hl7v2-sample2.json
的目录中,调用messages.create
方法以在 HL7v2 存储区中创建消息:curl
要创建 HL7v2 消息,请发出
POST
请求并指定以下信息:- 父数据集的名称
- HL7v2 存储区的名称
- 一条消息
- 访问令牌
以下示例显示了使用
curl
的POST
请求以及示例 JSON 文件hl7v2-sample2.json
。curl -X POST \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ --data-binary @hl7v2-sample2.json \ "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages"
如果请求成功,服务器将以 JSON 格式返回响应:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID", "data": "TVNIfF5+XCZ8QXxTRU5EX0ZBQ0lMSVRZXzJ8QXxBfDIwMTgwMTAxMDAwMDAwfHxUWVBFXkF8MjAxODAxMDEwMDAwMDB8VHwwLjB8fHxBQXx8MDB8QVNDSUkNRVZOfEEwMHwyMDE4MDEwMTA0MDAwMA1QSUR8fDE0ATExMV5eXl5NUk58MTExMTExMTFeXl5eTVJOfjExMTExMTExMTFeXl5eT1JHTk1CUg==", "sendFacility": "SEND_FACILITY_2", "sendTime": "2018-01-01T00:00:00Z", "messageType": "TYPE", "createTime": "1970-01-01T00:00:00Z", "patientIds": [ { "value": "14\u0001111", "type": "MRN" }, { "value": "11111111", "type": "MRN" }, { "value": "1111111111", "type": "ORGNMBR" } ] }
PowerShell
要创建 HL7v2 消息,请发出
POST
请求并指定以下信息:- 父数据集的名称
- HL7v2 存储区的名称
- 一条消息
- 访问令牌
以下示例显示了使用 Windows PowerShell 的
POST
请求以及示例 JSON 文件hl7v2-sample2.json
。$cred = gcloud auth application-default print-access-token $headers = @{ Authorization = "Bearer $cred" } Invoke-WebRequest ` -Method Post ` -Headers $headers ` -ContentType: "application/json; charset=utf-8" ` -InFile hl7v2-sample2.json ` -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages" | Select-Object -Expand Content
如果请求成功,服务器将以 JSON 格式返回响应:
{ "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID", "data": "TVNIfF5+XCZ8QXxTRU5EX0ZBQ0lMSVRZXzJ8QXxBfDIwMTgwMTAxMDAwMDAwfHxUWVBFXkF8MjAxODAxMDEwMDAwMDB8VHwwLjB8fHxBQXx8MDB8QVNDSUkNRVZOfEEwMHwyMDE4MDEwMTA0MDAwMA1QSUR8fDE0ATExMV5eXl5NUk58MTExMTExMTFeXl5eTVJOfjExMTExMTExMTFeXl5eT1JHTk1CUg==", "sendFacility": "SEND_FACILITY_2", "sendTime": "2018-01-01T00:00:00Z", "messageType": "TYPE", "createTime": "1970-01-01T00:00:00Z", "patientIds": [ { "value": "14\u0001111", "type": "MRN" }, { "value": "11111111", "type": "MRN" }, { "value": "1111111111", "type": "ORGNMBR" } ] }
请注意,sendFacility 为
SEND_FACILITY_2
,因此 Pub/Sub 通知只会发送到第二个 Pub/Sub 主题。创建消息后,第一个 MLLP 适配器不会返回任何响应,而第二个 MLLP 适配器会返回以下响应:I0214 00:00:00.000000 1 healthapiclient.go:266] Started to fetch message. I0214 00:00:00.000000 1 healthapiclient.go:283] Message was successfully fetched.
在运行第二个 Netcat 进程的终端中,将显示以下输出。此输出表明消息已发布。
connect to [127.0.0.1] from localhost [127.0.0.1] 39522 ^KMSH|^~\&|A|SEND_FACILITY_2|A|A|20180101000000||TYPE^A|20180101000000|T|0.0|||AA||00|ASCII^MEVN|A00|20180101040000^MPID||14^A111^^^^MRN|11111111^^^^MRN~1111111111^^^^ORGNMBR^\
此输出对应于您在创建消息时收到的响应的
data
字段中的值。它与hl7v2-sample2.json
文件中的data
值相同。
将 MLLP 适配器部署到 Google Kubernetes Engine
通过 MLLP 从您的护理中心传输 HL7v2 消息时,一种可能的配置是将消息发送到在 Google Cloud 中部署的适配器,并将其转发到 Cloud Healthcare API。
MLLP 适配器在 GKE 集群上作为无状态应用运行。GKE 集群是指由用于运行容器化应用的虚拟机实例组成的托管群组。无状态应用是不将数据或应用状态存储到集群或永久性存储空间的应用。此类应用会将数据和应用状态保留在客户端,因此可扩缩性更强。
GKE 使用 Deployment 控制器将无状态应用部署为统一且非唯一的 Pod。Deployment 会管理应用的“所需状态”,即应运行应用的 Pod 数、应运行的容器映像版本、应为 Pod 添加的标签等等。通过更新部署的 Pod 规范,可以动态地更改所需状态。
在部署适配器的同时,创建一个 Service 控制器,以便使用内部负载均衡将适配器连接到 Cloud Healthcare API。
如果您是 GKE 的新手,请完成 GKE 快速入门以了解产品的工作原理。
向 GKE 服务账号添加 Pub/Sub API 权限
如关于使用服务账号向 Cloud Platform 验证身份的 GKE 文档所述,容器集群中的每个节点都是一个 Compute Engine 实例。因此,当 MLLP 适配器在容器集群上运行时,它会自动继承其所部署到的 Compute Engine 实例的范围。
Google Cloud 会自动创建名为“Compute Engine 默认服务账号”的服务账号,并且 GKE 会将此服务账号与 GKE 创建的节点相关联。默认服务账号可能有权也可能无权使用其他 Cloud Platform API,具体取决于项目的配置方式。GKE 还会为 Compute Engine 实例分配一些有限的访问权限范围。
为获得最佳结果,请勿通过更新默认服务账号的权限或为 Compute Engine 实例分配更多访问权限范围,从 GKE 上运行的 Pod 向其他 Google Cloud 服务(如 Pub/Sub)验证身份。请创建您自己的服务账号。
您必须向容器集群授予必要的 Pub/Sub 权限,但还可以选择授予将指标写入 Cloud Monitoring 的权限。
要创建仅包含容器集群所需范围的新服务账号,请完成以下步骤:
控制台
创建服务账号:
在 Google Cloud 控制台中,转到创建服务账号页面。
选择一个项目。
在服务账号名称字段中,输入一个名称。Google Cloud 控制台会根据此名称填充服务账号 ID 字段。
可选:在服务账号说明字段中,输入说明。
点击创建。
点击选择角色字段。
在所有角色下,点击 Pub/Sub > Pub/Sub Subscriber。
点击添加其他角色,然后点击选择角色字段。
在所有角色下,点击 Cloud Healthcare > Healthcare HL7v2 Message Ingest。
可选:如果要启用监控,请点击添加其他角色,然后点击选择角色字段。
在所有角色下,点击 Monitoring > Monitoring Metric Writer。
点击继续。
点击完成以完成服务账号的创建过程。
不要关闭浏览器窗口。您将在下一个过程中使用该窗口。
创建服务账号密钥:
在 Google Cloud 控制台中,点击您创建的服务账号的电子邮件地址。
点击密钥。
依次点击添加密钥和创建新密钥。
点击创建。JSON 密钥文件将下载到您的计算机上。
点击关闭。
gcloud
要创建服务账号,请运行
gcloud iam service-accounts create
命令。gcloud iam service-accounts create SERVICE_ACCOUNT_NAME
输出是服务账号:
Created service account SERVICE_ACCOUNT_NAME.
要每个角色授予给服务账号,请运行
gcloud projects add-iam-policy-binding
命令。gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \ --role=roles/pubsub.subscriber gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \ --role=roles/healthcare.hl7V2Ingest gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \ --role=roles/monitoring.metricWriter
输出包括更新后的政策:
bindings: - members: - user:SERVICE_ACCOUNT_NAME role: roles/pubsub.publisher - members: - user:SERVICE_ACCOUNT_NAME roles/healthcare.hl7V2Ingest - members: - user:SERVICE_ACCOUNT_NAME roles/monitoring.metricWriter etag: ETAG version: 1
要创建服务账号密钥,请运行
gcloud iam service-accounts keys create
命令。gcloud iam service-accounts keys create ~/FILENAME.json \ --iam-account=SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com
创建服务账号后,系统会将包含服务账号凭据的 JSON 密钥文件下载到您的计算机。您需要使用此密钥文件来配置 MLLP 适配器,以使用
--service-account
标记在集群创建期间向 Cloud Healthcare API、Pub/Sub API 和 Cloud Monitoring API 验证身份。created key [e44da1202f82f8f4bdd9d92bc412d1d8a837fa83] of type [json] as [/usr/home/USERNAME/FILENAME.json] for [SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com]
创建集群
要在 GKE 中创建集群,请运行 gcloud container clusters create
命令:
gcloud container clusters create mllp-adapter \ --zone=COMPUTE_ZONE \ --service-account CLIENT_EMAIL
其中:
- COMPUTE_ZONE 是部署集群的可用区。可用区是您的集群及其资源所在的大致区域位置。例如,
us-west1-a
是us-west
区域中的可用区。如果使用gcloud config set compute/zone
设置了默认可用区,则此标志的值将替换默认值。 - CLIENT_EMAIL 是服务账号的标识符。您可以在
"client_email":
字段的服务账号密钥文件中找到此电子邮件地址。其格式如下:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com。
该命令会返回类似于以下示例的输出:
Creating cluster mllp-adapter in COMPUTE_ZONE... Cluster is being configured... Cluster is being deployed... Cluster is being health-checked... Cluster is being health-checked (master is healthy)...done. Created [https://container.googleapis.com/v1/projects/PROJECT_ID/zones/COMPUTE_ZONE/clusters/mllp-adapter]. To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/COMPUTE_ZONE/mllp-adapter?project=PROJECT_ID kubeconfig entry generated for mllp-adapter. NAME LOCATION MASTER_VERSION MASTER_IP MACHINE_TYPE NODE_VERSION NUM_NODES STATUS mllp-adapter COMPUTE_ZONE 1.11.7-gke.4 203.0.113.1 n1-standard-1 1.11.7-gke.4 3 RUNNING
创建集群后,GKE 会创建三个 Compute Engine 虚拟机实例。您可以通过使用以下命令列出实例来验证这一点:
gcloud compute instances list
配置部署
将应用部署到 GKE 时,您可以使用 Deployment 清单文件(通常是 YAML 文件)定义 Deployment 的属性。如需查看示例,请参阅创建 Deployment。
打开一个单独的终端。
使用文本编辑器创建名为
mllp_adapter.yaml
的 Deployment 清单文件,其中包含以下内容:
apiVersion: apps/v1 kind: Deployment metadata: name: mllp-adapter-deployment spec: replicas: 1 selector: matchLabels: app: mllp-adapter template: metadata: labels: app: mllp-adapter spec: containers: - name: mllp-adapter imagePullPolicy: Always image: gcr.io/cloud-healthcare-containers/mllp-adapter ports: - containerPort: 2575 protocol: TCP name: "port" command: - "/usr/mllp_adapter/mllp_adapter" - "--port=2575" - "--hl7_v2_project_id=PROJECT_ID" - "--hl7_v2_location_id=LOCATION" - "--hl7_v2_dataset_id=DATASET_ID" - "--hl7_v2_store_id=HL7V2_STORE_ID" - "--api_addr_prefix=https://healthcare.googleapis.com:443/v1" - "--logtostderr" - "--receiver_ip=0.0.0.0"
其中:
- PROJECT_ID 是包含 HL7v2 存储区的 Google Cloud 项目的 ID。
- LOCATION 是 HL7v2 存储区所在的区域。
- DATASET_ID 是 HL7v2 存储区的父数据集的 ID。
- HL7V2_STORE_ID 是您要向其发送 HL7v2 消息的 HL7v2 存储区 ID。
Deployment 具有以下属性:
spec: replicas:
是 Deployment 管理的副本 Pod 数。spec: template: metadata: labels:
是为每个 Pod 指定的标签,供 Deployment 用来管理 Pod。spec: template: spec:
是 Pod 规范,用于定义每个 Pod 的运行方式。spec: containers
包括要在每个 Pod 中运行的容器的名称以及应运行的容器映像。
如需详细了解 Deployment 规范,请参阅 Deployment API 参考。
配置 Service
要使 MLLP 适配器可供集群外部的应用(如护理中心)访问,您必须配置内部负载均衡器。
如果尚未配置 VPN,只要应用使用相同的 VPC 网络并位于同一 Google Cloud 区域中,应用就可以通过内部负载均衡器访问 MLLP 适配器。例如,要使适配器可供同一区域内和同一 VPC 网络中的 Compute Engine 虚拟机实例访问,您可以向集群的 Service 资源添加内部负载均衡器。
在创建 Deployment 清单文件的目录中,使用文本编辑器创建名为 mllp_adapter_service.yaml
的 Service 清单文件,其中包含以下内容。此文件负责配置内部负载均衡:
apiVersion: v1
kind: Service
metadata:
name: mllp-adapter-service
annotations:
cloud.google.com/load-balancer-type: "Internal"
spec:
type: LoadBalancer
ports:
- name: port
port: 2575
targetPort: 2575
protocol: TCP
selector:
app: mllp-adapter
该 Service 具有以下属性:
metadata: name:
是您为 Service 选择的名称。在本例中为mllp-adapter-service
。metadata: annotations:
是一个注解,指定要配置内部负载平衡器。spec: type:
是负载均衡器的类型。ports: port:
用于指定服务可以从同一集群中的其他 Service 接收流量的端口。使用默认的2575
MLLP 端口。ports: targetPort:
用于在 Service 运行的每个 Pod 上指定端口。spec: selector: app:
用于指定作为 Service 目标的 Pod。
虽然可以为负载均衡器指定 IP 地址(使用 clusterIP
字段),但负载均衡器可以生成自己的 IP 地址,以便您向其发送消息。现在,请让集群生成 IP 地址,您将在本教程的后面部分用到该地址。
如需详细了解内部负载均衡,请参阅 GKE 文档。
如需详细了解 Service 规范,请参阅 Service API 参考文档。
部署 Deployment
要将适配器部署到 GKE 集群,请在包含 mllp_adapter.yaml
Deployment 清单文件的目录中运行以下命令:
kubectl apply -f mllp_adapter.yaml
该命令返回以下输出:
deployment.extensions "mllp-adapter-deployment" created
检查 Deployment
创建部署后,您可以使用 kubectl
工具对其进行检查。
要获取有关 Deployment 的详细信息,请运行以下命令:
kubectl describe deployment mllp-adapter
要列出 Deployment 创建的 Pod,请运行以下命令:
kubectl get pods -l app=mllp-adapter
要获取有关所创建的 Pod 的信息,请执行以下操作:
kubectl describe pod POD_NAME
如果 Deployment 成功,上一个命令的输出的最后部分应包含以下信息:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 1m default-scheduler Successfully assigned default/mllp-adapter-deployment-85b46f8-zxw68 to gke-mllp-adapter-default-pool-9c42852d-95sn
Normal Pulling 1m kubelet, gke-mllp-adapter-default-pool-9c42852d-95sn pulling image "gcr.io/cloud-healthcare-containers/mllp-adapter"
Normal Pulled 1m kubelet, gke-mllp-adapter-default-pool-9c42852d-95sn Successfully pulled image "gcr.io/cloud-healthcare-containers/mllp-adapter"
Normal Created 1m kubelet, gke-mllp-adapter-default-pool-9c42852d-95sn Created container
Normal Started 1m kubelet, gke-mllp-adapter-default-pool-9c42852d-95sn Started container
部署 Service 并创建内部负载均衡器
要创建内部负载均衡器,请在包含 mllp_adapter_service.yaml
Service 清单文件的目录中运行以下命令:
kubectl apply -f mllp_adapter_service.yaml
该命令返回以下输出:
service "mllp-adapter-service" created
检查 Service
创建 Service 后,请检查以验证其是否已成功配置。
要检查内部负载均衡器,请运行以下命令:
kubectl describe service mllp-adapter-service
该命令的输出类似于以下示例:
Name: mllp-adapter-service
Namespace: default
Labels: <none>
Annotations: cloud.google.com/load-balancer-type=Internal
kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{"cloud.google.com/load-balancer-type":"Internal"},"name":"mllp-adapter-service","namespa...
Selector: app=mllp-adapter
Type: LoadBalancer
IP: 203.0.113.1
LoadBalancer Ingress: 203.0.113.1
Port: port 2575/TCP
TargetPort: 2575/TCP
NodePort: port 30660/TCP
Endpoints: <none>
Session Affinity: None
External Traffic Policy: Cluster
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal EnsuringLoadBalancer 1m service-controller Ensuring load balancer
Normal EnsuredLoadBalancer 1m service-controller Ensured load balancer
LoadBalancer Ingress
IP 地址可能需要长达一分钟来填充。在下一步中,您需要使用此 IP 地址和 2575
端口从集群外部访问 Service。
创建 Compute Engine 虚拟机并发送消息
在本教程前面的部分中,您在本地测试了 MLLP 适配器并向您的 HL7v2 存储区发送了 HL7v2 消息,而现在需要将消息从 Compute Engine 虚拟机发送到在 GKE 上运行的 MLLP 适配器。然后,系统会将这些消息转发到 HL7v2 存储区。
要将请求从新实例发送到 GKE 集群,该实例和现有实例必须位于同一区域并使用同一 VPC 网络。
在本部分的结尾处,您需要列出发布到 Pub/Sub 主题的通知以及 HL7v2 存储区中的 HL7v2 消息。Compute Engine 虚拟机实例必须获得执行这些任务的权限。在创建实例之前,请按照以下步骤创建具有所需权限的新服务账号:
控制台
创建服务账号:
在 Google Cloud 控制台中,转到创建服务账号页面。
选择一个项目。
在服务账号名称字段中,输入一个名称。Google Cloud 控制台会根据此名称填充服务账号 ID 字段。
可选:在服务账号说明字段中,输入说明。
点击创建。
点击选择角色字段。
在所有角色下,点击 Pub/Sub > Pub/Sub Subscriber。
点击添加其他角色,然后点击选择角色字段。
在所有角色下,点击 Cloud Healthcare > Healthcare HL7v2 Message Consumer。
点击继续。
点击完成以完成服务账号的创建过程。
不要关闭浏览器窗口。您将在下一个过程中使用该窗口。
创建服务账号密钥:
在 Google Cloud 控制台中,点击您创建的服务账号的电子邮件地址。
点击密钥。
依次点击添加密钥和创建新密钥。
点击创建。JSON 密钥文件将下载到您的计算机上。
点击关闭。
gcloud
要创建服务账号,请运行
gcloud iam service-accounts create
命令。gcloud iam service-accounts create SERVICE_ACCOUNT_NAME
输出是服务账号:
Created service account SERVICE_ACCOUNT_NAME.
要每个角色授予给服务账号,请运行
gcloud projects add-iam-policy-binding
命令。gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \ --role=roles/pubsub.publisher gcloud projects add-iam-policy-binding PROJECT_ID \ --member=serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \ --role=roles/healthcare.hl7V2Consumer
输出包括更新后的政策:
bindings: - members: - user:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com role: roles/pubsub.publisher - members: - user:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com roles/healthcare.hl7V2Consumer etag: ETAG version: 1
要创建服务账号密钥,请运行
gcloud iam service-accounts keys create
命令。gcloud iam service-accounts keys create ~/FILENAME.json \ --iam-account=SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com
创建服务账号后,系统会将包含服务账号凭据的 JSON 密钥文件下载到您的计算机。
以下步骤展示了如何在 Compute Engine 中创建 Linux 虚拟机实例:
控制台
在 Google Cloud 控制台中,进入虚拟机实例页面。
点击创建实例。
为与您在创建集群时所选可用区匹配的实例选择区域和可用区。例如,如果在创建集群时为 COMPUTE_ZONE 使用了
us-central1-a
,则在实例创建屏幕中,为区域选择us-central1 (Iowa)
,为可用区选择us-central1-a
。在启动磁盘部分中,点击更改以开始配置您的启动磁盘。
在公共映像标签页上,选择 Debian 操作系统的版本 9。
点击选择。
在身份和 API 访问权限部分,选择您创建的服务账号。
在防火墙部分,选择允许 HTTP 流量。
点击创建以创建实例。
gcloud
要创建计算实例,请使用以下选项运行 gcloud compute instances create
方法:
- 您在创建集群时选择的 ZONE
- 允许 HTTP 流量的
http-server
代码 - 您创建的 SERVICE_ACCOUNT
gcloud compute instances create COMPUTE_NAME \ --project=PROJECT_ID \ --zone=ZONE \ --image-family=debian-9 \ --image-project=debian-cloud \ --tags=http-server \ --service-account=SERVICE_ACCOUNT
输出类似于以下示例:
Created [https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/COMPUTE_NAME]. NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS COMPUTE_NAME ZONE n1-standard-1 INTERNAL_IP EXTERNAL_IP RUNNING
实例启动需要您稍等片刻。启动实例后,该实例将在“虚拟机实例”页面列出,并带有绿色状态图标。
默认情况下,实例使用的默认 VPC 网络与集群使用的相同,这意味着流量可以从实例发送到集群。
要连接到实例,请完成以下步骤:
控制台
在 Google Cloud 控制台中,打开虚拟机实例页面。
在虚拟机实例列表中,点击您创建的实例行中的 SSH。
gcloud
要连接到实例,请运行 gcloud compute ssh
命令:
gcloud compute ssh INSTANCE_NAME \ --project PROJECT_ID \ --zone ZONE
您现在具有一个用来与您的 Linux 实例互动的终端窗口。
在终端窗口中,安装 Netcat:
sudo apt install netcat
下载
hl7v2-mllp-sample.txt
文件并将其保存到实例。如需了解文件中使用的编码和细分终止符,请参阅 HL7v2 消息细分分隔符和编码。要开始通过 MLLP 适配器将 HL7v2 消息发送到您的 HL7v2 存储区,请在下载该文件的目录中运行以下命令。使用您在检查 Service 时显示的
LoadBalancer Ingress
值。echo -n -e "\x0b$(cat hl7v2-mllp-sample.txt)\x1c\x0d" | nc LOAD_BALANCER_INGRESS_IP_ADDRESS 2575
运行该命令后,系统会通过 MLLP 适配器将消息发送到您的 HL7v2 存储区。如果已将消息成功提取到 HL7v2 存储区中,则该命令将返回以下输出:
MSA|AA|20150503223000|ILITY|FROM_APP|FROM_FACILITY|20190312162410||ACK|f4c59243-19c2-4373-bea0-39c1b2ba616b|P|2.5
此输出表明 HL7v2 存储区以
AA
(Application Accept
) 响应类型进行响应,这意味着消息已通过验证并成功提取。如需查看发布到 Pub/Sub 主题的消息,请运行
gcloud pubsub subscriptions pull
命令:gcloud pubsub subscriptions pull --auto-ack PUBSUB_SUBSCRIPTION
该命令返回有关提取的 HL7v2 消息的以下输出:
┌-----------------------------------------------------------------------------------------------------------------|-----------------|---------------┐ | DATA | MESSAGE_ID | ATTRIBUTES | ├-----------------------------------------------------------------------------------------------------------------|-----------------|---------------| | projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/HL7V2_MESSAGE_ID | 123456789012345 | msgType=ADT | └-----------------------------------------------------------------------------------------------------------------|-----------------|---------------┘
您还可以列出 HL7v2 存储区中的消息,以查看消息是否已添加:
curl
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages"
如果请求成功,服务器将在资源路径中返回消息的 ID:
{ "hl7V2Messages": [ { "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID" } ] }
PowerShell
$cred = gcloud auth application-default print-access-token $headers = @{ Authorization = "Bearer $cred" } Invoke-WebRequest ` -Method Get ` -Headers $headers ` -ContentType: "application/json; charset=utf-8" ` -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages" | Select-Object -Expand Content
如果请求成功,服务器将在资源路径中返回消息的 ID:
{ "hl7V2Messages": [ { "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID" } ] }
完成此部分后,您已将 MLLP 适配器成功部署到 GKE,并通过该适配器将一条 HL7v2 消息从远程实例发送到了 Cloud Healthcare API。
在本教程的其余部分中,您将学习如何在 Compute Engine 实例(充当“本地”实例)和适配器之间配置 VPN,从而安全地为传输的 HL7v2 消息加密。
配置 VPN
使用 VPN 允许您通过公共网络(例如互联网)扩展用于发送 HL7v2 消息的专用网络。通过使用 VPN,您可以通过 MLLP 适配器将消息从您的护理中心发送到 Google Cloud。此流程中的系统会像在单个专用网络上一样运行。
有两种方法可以使用 VPN 来保护 MLLP 连接:
- 使用 Cloud VPN
- 使用 Strongswan on Docker 端到端 VPN 解决方案
配置 Cloud VPN
Cloud VPN 通过 IPsec VPN 连接将您的本地网络安全地连接到 Google Cloud Virtual Private Cloud (VPC) 网络。两个网络之间的流量传输通过一个 VPN 网关加密,然后通过另一个 VPN 网关解密,这样可以在通过互联网或通过护理中心网络传输数据时保护数据。
在本教程中,您配置的每个 VPN 网关都位于不同的自定义网络和不同的 Google Cloud 区域内的子网中。
在 us-central1
中配置的 VPN 网关在 Google Cloud 端充当 Cloud VPN 网关,而 europe-west1
中的 Cloud VPN 网关模拟您的“本地”网关。
命名和寻址参考
出于参考用途,本教程入门使用以下命名和 IP 地址:
Google Cloud 端
- 网络名称:
cloud-vpn-network
- 子网名称:
subnet-us-central-10-0-1
- 区域:
us-central1
- 子网范围:
10.0.1.0/24
- 外部 IP 地址名称:
cloud-vpn-ip
- VPN 网关名称:
vpn-us-central
- VPN 隧道名称:
vpn-us-central-tunnel-1
“本地”端
- 网络名称:
on-prem-vpn-network
- 子网名称:
subnet-europe-west-10-0-2
- 区域:
europe-west1
- 子网范围:
10.0.2.0/24
- 外部 IP 地址名称:
on-prem-vpn-ip
- VPN 网关名称:
vpn-europe-west
- VPN 隧道名称:
vpn-europe-west-tunnel-1
创建自定义 VPC 网络和子网
配置 Cloud VPN 的第一步是创建两个 VPC 网络。一个名为 on-prem-vpn-network
的网络在“本地”环境中进行配置,并在名为 on-prem-instance
的 Compute Engine 虚拟机实例上运行。另一个网络(称为 cloud-vpn-network
)是运行 MLLP 适配器的 GKE 集群使用的网络。您需要连接到 on-prem-instance
虚拟机,并通过 MLLP 适配器的内部负载均衡器向在 cloud-vpn-network
网络下运行的 MLLP 适配器发送 HL7v2 消息。
通过完成以下步骤创建两个自定义 VPC 网络及其子网:
要创建第一个 VPC 网络
cloud-vpn-network
,请运行以下命令:gcloud compute networks create cloud-vpn-network \ --project=PROJECT_ID \ --subnet-mode=custom
要为
cloud-vpn-network
网络创建subnet-us-central-10-0-1
子网,请运行以下命令:gcloud compute networks subnets create subnet-us-central-10-0-1 \ --project=PROJECT_ID \ --region=us-central1 \ --network=cloud-vpn-network \ --range=10.0.1.0/24
要创建
on-prem-vpn-network
VPC 网络,请运行以下命令:gcloud compute networks create on-prem-vpn-network \ --project=PROJECT_ID \ --subnet-mode=custom
要为
on-prem-vpn-network
VPC 网络创建subnet-europe-west-10-0-2
子网,请运行以下命令:gcloud compute networks subnets create subnet-europe-west-10-0-2 \ --project=PROJECT_ID \ --region=europe-west1 \ --network=on-prem-vpn-network \ --range=10.0.2.0/24
创建外部 IP 地址
在创建 VPN 网关之前,请通过完成以下步骤为每个网关保留外部 IP 地址:
要为
cloud-vpn-ip
地址保留区域外部(静态)IP 地址,请运行以下命令:gcloud compute addresses create cloud-vpn-ip \ --project=PROJECT_ID \ --region=us-central1
要为
on-prem-vpn-ip
地址保留区域外部(静态)IP 地址,请运行以下命令:gcloud compute addresses create on-prem-vpn-ip \ --project=PROJECT_ID \ --region=europe-west1
记下外部 IP 地址,以便在下一部分中使用它们配置 VPN 网关。要检索外部 IP 地址,请运行以下命令:
Cloud VPN IP 地址:
gcloud compute addresses describe cloud-vpn-ip \ --project PROJECT_ID \ --region us-central1 \ --format='flattened(address)'
“本地”VPN IP 地址:
gcloud compute addresses describe on-prem-vpn-ip \ --project PROJECT_ID \ --region europe-west1 \ --format='flattened(address)'
这些命令会返回类似于以下内容的输出:
address: 203.0.113.1
创建 VPN 网关、隧道和路由
完成以下步骤,为 Cloud VPN 创建 VPN 网关、隧道和路由:
按照生成强预共享密钥中的说明创建加密型强预共享密钥(共享密钥令牌)。此密钥在本部分中引用为 SHARED_SECRET。
要创建目标 VPN 网关对象,请运行以下命令:
gcloud compute target-vpn-gateways create vpn-us-central \ --project PROJECT_ID \ --region us-central1 \ --network cloud-vpn-network
要创建三条转发规则,请运行以下命令,并将 CLOUD_VPN_EXTERNAL_ADDRESS 变量替换为上一部分中 Cloud VPN IP 地址的值:
向网关发送 ESP (IPsec) 流量:
gcloud compute forwarding-rules create vpn-us-central-rule-esp \ --project PROJECT_ID \ --region us-central1 \ --address CLOUD_VPN_EXTERNAL_ADDRESS \ --ip-protocol ESP \ --target-vpn-gateway vpn-us-central
将 UDP 500 流量发送到网关:
gcloud compute forwarding-rules create vpn-us-central-rule-udp500 \ --project PROJECT_ID \ --region us-central1 \ --address CLOUD_VPN_EXTERNAL_ADDRESS \ --ip-protocol UDP \ --ports 500 \ --target-vpn-gateway vpn-us-central
向网关发送 UDP 4500 流量:
gcloud compute forwarding-rules create vpn-us-central-rule-udp4500 \ --project PROJECT_ID \ --region us-central1 \ --address CLOUD_VPN_EXTERNAL_ADDRESS \ --ip-protocol UDP \ --ports 4500 \ --target-vpn-gateway vpn-us-central
要创建连接到 Cloud VPN 网关的隧道,请运行以下命令。将 ON_PREM_VPN_IP 替换为上一部分中“本地” VPN IP 地址中的值。
gcloud compute vpn-tunnels create vpn-us-central-tunnel-1 \ --project PROJECT_ID \ --region us-central1 \ --peer-address ON_PREM_VPN_IP \ --shared-secret SHARED_SECRET \ --ike-version 2 \ --local-traffic-selector 0.0.0.0/0 \ --target-vpn-gateway vpn-us-central
要创建到
10.0.2.0/24
的静态路由,请运行以下命令:gcloud compute routes create "vpn-us-central-tunnel-1-route-1" \ --project PROJECT_ID \ --network "cloud-vpn-network" \ --next-hop-vpn-tunnel "vpn-us-central-tunnel-1" \ --next-hop-vpn-tunnel-region "us-central1" \ --destination-range "10.0.2.0/24"
完成以下步骤,为“本地”VPN 创建 VPN 网关、隧道和路由:
要创建目标 VPN 网关对象,请运行以下命令:
gcloud compute target-vpn-gateways create "vpn-europe-west" \ --project PROJECT_ID \ --region "europe-west1" \ --network "on-prem-vpn-network"
要创建三条转发规则,请运行以下命令,并将 ON_PREMISES_VPN_EXTERNAL_ADDRESS 变量替换为上一部分中“本地”VPN IP 地址中的值:
向网关发送 ESP (IPsec) 流量:
gcloud compute forwarding-rules create vpn-europe-west-rule-esp \ --project PROJECT_ID \ --region europe-west1 \ --address ON_PREMISES_VPN_EXTERNAL_ADDRESS \ --ip-protocol ESP \ --target-vpn-gateway vpn-europe-west
将 UDP 500 流量发送到网关:
gcloud compute forwarding-rules create vpn-europe-west-rule-udp500 \ --project PROJECT_ID \ --region europe-west1 \ --address ON_PREMISES_VPN_EXTERNAL_ADDRESS \ --ip-protocol UDP \ --ports 500 \ --target-vpn-gateway vpn-europe-west
向网关发送 UDP 4500 流量:
gcloud compute forwarding-rules create vpn-europe-west-rule-udp4500 \ --project PROJECT_ID \ --region europe-west1 \ --address ON_PREMISES_VPN_EXTERNAL_ADDRESS \ --ip-protocol UDP \ --ports 4500 \ --target-vpn-gateway vpn-europe-west
要创建连接到“本地”网关的隧道,请运行以下命令:
gcloud compute vpn-tunnels create vpn-europe-west-tunnel-1 \ --project PROJECT_ID \ --region europe-west1 \ --peer-address CLOUD_VPN_IP \ --shared-secret SHARED_SECRET \ --ike-version 2 \ --local-traffic-selector 0.0.0.0/0 \ --target-vpn-gateway vpn-europe-west
要创建到
10.0.1.0/24
的静态路由,请运行以下命令:gcloud compute routes create "vpn-europe-west-tunnel-1-route-1" \ --project PROJECT_ID \ --network "on-prem-vpn-network" \ --next-hop-vpn-tunnel "vpn-europe-west-tunnel-1" \ --next-hop-vpn-tunnel-region "europe-west1" \ --destination-range "10.0.1.0/24"
您已创建 Cloud VPN 和“本地”网关并启动了其隧道。在您创建防火墙规则以允许流量通过它们之间的隧道之前,这些 VPN 网关不会连接。
创建防火墙规则
您必须为 VPN 隧道的两端创建防火墙规则。这些规则允许所有 TCP、UDP 和 ICMP 流量从 VPN 隧道一端的子网进入并流向另一端。
要为 Cloud VPN 子网创建防火墙规则,请运行以下命令:
gcloud compute firewall-rules create allow-tcp-udp-icmp-cloud-vpn \ --project=PROJECT_ID \ --direction=INGRESS \ --priority=1000 \ --network=cloud-vpn-network \ --action=ALLOW \ --rules=tcp,udp,icmp \ --source-ranges=10.0.2.0/24
要为“本地”子网创建防火墙规则,请运行以下命令:
gcloud compute firewall-rules create allow-tcp-udp-icmp-on-prem-vpn \ --project=PROJECT_ID \ --direction=INGRESS \ --priority=1000 \ --network=on-prem-vpn-network \ --action=ALLOW \ --rules=tcp,udp,icmp \ --source-ranges=10.0.1.0/24
创一条建防火墙规则,允许通过运行以下命令来让 SSH 连接到端口 22 上的虚拟机实例:
gcloud compute firewall-rules create on-prem-vpn-allow-ssh \ --project=PROJECT_ID \ --direction=INGRESS \ --priority=1000 \ --network=on-prem-vpn-network \ --action=ALLOW \ --rules=tcp:22 \ --source-ranges=0.0.0.0/0
检查 VPN 隧道的状态
要验证隧道是否已启动,请完成以下步骤:
进入 Google Cloud 控制台中的 VPN 页面。
点击 Google VPN 隧道标签页。
在每个隧道的状态字段中,查找绿色对勾标记和“已建立”字样。如果有这些项目,则说明您的网关已经协商好了隧道。如果几分钟后没有标记出现,则请参阅问题排查。
如需了解与 VPN 隧道相关的其他日志记录信息,请参阅“问题排查”页面上的检查 VPN 日志。例如,您可以查看有关已丢弃数据包、隧道状态、已接收字节和已发送字节的指标。
现在,您已成功为 Cloud VPN 配置必要的网关、隧道和防火墙规则,现在可以在“本地”虚拟机实例与在 GKE 上运行的 MLLP 适配器之间创建安全连接。
将 Deployment 合并到 GKE 和 Cloud VPN
在本教程前面的部分中,您在本地测试了 MLLP 适配器并通过非 VPN 连接向该 MLLP 适配器发送了 HL7v2 消息,而现在您需要使用 Cloud VPN,通过安全连接从 Compute Engine 虚拟机向在 GKE 上运行的 MLLP 适配器发送消息。然后,系统会将这些消息转发到 HL7v2 存储区。
重新创建 Deployment
首先,在 GKE 上重新创建部署,以便集群使用您在配置 Cloud VPN 中配置的设置:
要删除您创建的
mllp-adapter
集群,请运行gcloud container clusters delete
命令。输入您在创建集群时使用的 COMPUTE_ZONE 值。gcloud container clusters delete mllp-adapter --zone=COMPUTE_ZONE
按照将 MLLP 适配器部署到 Kubernetes Engine 中的步骤操作,但在 GKE 中创建集群时,添加您在创建自定义 VPN 网络和子网中创建的
cloud-vpn-network
网络和subnet-us-central-10-0-1
子网。确保集群创建命令如下所示:
gcloud container clusters create mllp-adapter \ --zone=COMPUTE_ZONE \ --service-account=CLIENT_EMAIL \ --network=cloud-vpn-network \ --subnetwork=subnet-us-central-10-0-1
其中:
COMPUTE_ZONE 是部署集群的可用区。在上一部分中配置 Cloud VPN 时,您将“Google Cloud 端”网络设置为使用
us-central1
。此“Google Cloud 端”网络是运行 GKE 集群的网络。在us-central1
中使用以下任一可用区:us-central1-c
、us-central1-a
、us-central1-f
、us-central1-b
。CLIENT_EMAIL 是服务账号的标识符。您可以在
"client_email":
字段的服务账号密钥文件中找到此信息。其格式如下:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com。
使用网络设置创建新的 Compute Engine 虚拟机
以下步骤展示了如何使用 Google Cloud 控制台在 Compute Engine 中创建 Linux 虚拟机实例。与您创建的 Compute Engine 虚拟机不同,此虚拟机使用“本地端”网络设置通过 VPN 与 GKE 集群进行通信。
控制台
在 Google Cloud 控制台中,打开虚拟机实例页面。
点击创建实例。
为与“本地端”网络设置匹配的实例选择区域和可用区:为区域选择
europe-west1 (Belgium)
,为可用区选择europe-west1-b
。在启动磁盘部分中,点击更改以开始配置您的启动磁盘。
在公共映像标签页上,选择 Debian 操作系统的版本 9。
点击选择。
在身份和 API 访问权限部分,选择您创建的服务账号。
在防火墙部分,选择允许 HTTP 流量。
展开管理、安全、磁盘、网络、单独租用部分。
在网络标签页的网络接口下方,指定“本地端”网络设置的网络详细信息。
- 在网络字段中,选择 on-prem-vpn-network。
- 在子网字段,选择 subnet-europe-west-10-0-2 (10.0.2.0/24)。
点击创建以创建实例。
实例启动需要您稍等片刻。准备就绪后,它会在“虚拟机实例”页面上列出,并带有绿色状态图标。
gcloud
要创建计算实例,请使用以下选项运行 gcloud compute instances create
方法:
- 与“本地”端网络设置匹配的 ZONE:为区域选择
europe-west1-b
。 - 通过指定
http-server
标记允许 HTTP 流量 - 您创建的 SERVICE_ACCOUNT
gcloud compute instances create COMPUTE_NAME \ --project=PROJECT_ID --zone=ZONE --image-family=debian-9 \ --tags=http-server,https-server --service-account=SERVICE_ACCOUNT
输出类似于以下示例:
Created [https://www.googleapis.com/compute/v1/projects/PROJECT_ID/zones/ZONE/instances/COMPUTE_NAME]. NAME ZONE MACHINE_TYPE PREEMPTIBLE INTERNAL_IP EXTERNAL_IP STATUS COMPUTE_NAME ZONE n1-standard-1 INTERNAL_IP EXTERNAL_IP RUNNING
要连接到实例,请完成以下步骤:
控制台
在 Google Cloud 控制台中,打开虚拟机实例页面。
在虚拟机实例列表中,点击您创建的实例行中的 SSH。
gcloud
要连接到实例,请运行 gcloud compute ssh
命令:
gcloud compute ssh INSTANCE_NAME \ --project PROJECT_ID \ --zone ZONE
您现在具有一个用来与您的 Linux 实例互动的终端窗口。
在终端窗口中,安装 Netcat:
sudo apt install netcat
下载
hl7v2-mllp-sample.txt
文件并将其保存到实例。要开始通过 MLLP 适配器将 HL7v2 消息发送到您的 HL7v2 存储区,请在下载该文件的目录中运行以下命令。使用您在检查 Service 时显示的
LoadBalancer Ingress
值。echo -n -e "\x0b$(cat hl7v2-mllp-sample.txt)\x1c\x0d" | nc LOAD_BALANCER_INGRESS_IP_ADDRESS 2575
运行该命令后,系统会通过 MLLP 适配器将消息发送到您的 HL7v2 存储区。如果已将消息成功提取到 HL7v2 存储区中,则该命令将返回以下输出:
MSA|AA|20150503223000|ILITY|FROM_APP|FROM_FACILITY|20190312162410||ACK|f4c59243-19c2-4373-bea0-39c1b2ba616b|P|2.5
此输出表明 HL7v2 存储区以
AA
(Application Accept
) 响应类型进行响应,这意味着消息已通过验证并成功提取。如需查看发布到 Pub/Sub 主题的消息,请运行
gcloud pubsub subscriptions pull
命令:gcloud pubsub subscriptions pull --auto-ack PUBSUB_SUBSCRIPTION
该命令返回有关提取的 HL7v2 消息的以下输出:
┌-----------------------------------------------------------------------------------------------------------------|-----------------|---------------┐ | DATA | MESSAGE_ID | ATTRIBUTES | ├-----------------------------------------------------------------------------------------------------------------|-----------------|---------------| | projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/HL7V2_MESSAGE_ID | 123456789012345 | msgType=ADT | └-----------------------------------------------------------------------------------------------------------------|-----------------|---------------┘
您还可以列出 HL7v2 存储区中的消息,以查看消息是否已添加:
curl
curl -X GET \ -H "Authorization: Bearer $(gcloud auth application-default print-access-token)" \ -H "Content-Type: application/json; charset=utf-8" \ "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages"
如果请求成功,服务器将在资源路径中返回消息的 ID:
{ "hl7V2Messages": [ { "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID" } ] }
PowerShell
$cred = gcloud auth application-default print-access-token $headers = @{ Authorization = "Bearer $cred" } Invoke-WebRequest ` -Method Get ` -Headers $headers ` -ContentType: "application/json; charset=utf-8" ` -Uri "https://healthcare.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages" | Select-Object -Expand Content
如果请求成功,服务器将在资源路径中返回消息的 ID:
{ "hl7V2Messages": [ { "name": "projects/PROJECT_ID/locations/LOCATION/datasets/DATASET_ID/hl7V2Stores/HL7V2_STORE_ID/messages/MESSAGE_ID" } ] }
完成此部分后,您已将 MLLP 适配器成功部署到 GKE,并使用 VPN,通过该适配器将一条 HL7v2 消息从“本地”实例安全地发送到了 Cloud Healthcare API。
清理
为避免系统因本快速入门中使用的资源向您的 Google Cloud 账号收取费用,您可以清理在 Google Cloud 上创建的资源。
删除项目
按照以下步骤删除您在本教程中创建的项目:
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
问题排查
适配器故障
将 MLLP 适配器部署到 GKE 后,该适配器发生故障。
- 按照已部署工作负载的问题排查中的步骤操作。
在本地运行时出现 Connection refused
错误
在本地测试 MLLP 适配器时,您会遇到错误 Connection refused
。
某些 Mac OS 用户会遇到此错误。请使用
-p 2575:2575
,而不要使用--network=host
标志。此外,请设置--receiver_ip=0.0.0.0
,而不是设置--receiver_ip=127.0.0.0
。该命令应如下所示:docker run \ -p 2575:2575 \ gcr.io/cloud-healthcare-containers/mllp-adapter \ /usr/mllp_adapter/mllp_adapter \ --hl7_v2_project_id=PROJECT_ID \ --hl7_v2_location_id=LOCATION \ --hl7_v2_dataset_id=DATASET_ID \ --hl7_v2_store_id=HL7V2_STORE_ID \ --export_stats=false \ --receiver_ip=0.0.0.0 \ --pubsub_project_id=PROJECT_ID \ --pubsub_subscription=PUBSUB_SUBSCRIPTION \ --api_addr_prefix=https://healthcare.googleapis.com:443/v1 \ --logtostderr
在本地运行时出现 could not find default credentials
错误
在本地测试 MLLP 适配器时,您会遇到错误 healthapiclient.NewHL7V2Client: oauth2google.DefaultTokenSource: google: could not find default credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.
。
当适配器找不到您的 Google Cloud 凭据时,会出现此错误。要修复该错误,请在重新运行该命令之前尝试以下方法之一:
- 按照为服务器到服务器生产应用设置身份验证中的说明进行操作,以确认适配器可以找到您的 Google Cloud 凭据。
- 安装并初始化 Google Cloud CLI 以访问 gcloud CLI。请确保在要在本地测试适配器的机器上向 gcloud CLI 授权。
身份验证错误
如果您在在本地测试 MLLP 适配器时遇到任何身份验证错误(本部分其他地方并未介绍的错误),请重新运行 docker run
命令并在命令末尾添加 -v ~/.config:/root/.config
标志,如下所示:
docker run \
-v ~/.config:/root/.config \
...