简而言之: Subscription(订阅)用于告知 FHIR 服务器“当满足这些条件的资源发生变化时,请通知此端点”。在 FHIR R4 中,条件是一个搜索字符串(criteria: "Observation?patient=123&code=85354-9"),服务器会将匹配的资源发送到 REST hook、websocket、电子邮件或 FHIR 消息。在 R4B 和 R5 中,模型围绕 SubscriptionTopic 重建:服务器发布它可以通知的事件,客户端使用过滤器订阅某个主题,通知会以 subscription-notification 类型的 Bundle 的形式到达,该 Bundle 始终以 SubscriptionStatus 资源开头。Subscriptions R5 Backport 实现指南允许 R4 服务器提供新模型。
R4:基于条件的订阅
在 FHIR R4 中,订阅是基于条件的:客户端创建一个 Subscription 资源,其 criteria 是一个搜索字符串,例如 Observation?code=…&patient=…,并且其 channel 是 rest-hook、websocket、email、sms 或 message。服务器会针对每一次创建和更新评估 criteria,并将匹配的资源或空通知 POST 到 endpoint。
{
"resourceType": "Subscription",
"status": "requested",
"reason": "Blood pressure alerts for the hypertension clinic",
"criteria": "Observation?code=http://loinc.org|85354-9&patient=Patient/123",
"channel": {
"type": "rest-hook",
"endpoint": "https://clinic.example.org/hooks/bp",
"payload": "application/fhir+json",
"header": ["Authorization: Bearer <token>"]
}
}
服务器会针对每次创建和更新评估条件。当资源匹配时,它会将该资源 POST 到端点(如果省略了 payload,则 POST 一个空主体,以便客户端自行获取资源)。这样做有效,但存在三个问题:服务器无法说明它们支持哪些条件,客户端无法区分错过的通知和静默期,并且“资源匹配搜索”不等于“事件发生”(例如,Encounter 结束无法通过搜索来表达)。
R4B 和 R5:基于主题的订阅
在 FHIR R4B 和 R5 中,订阅是基于主题的。服务器会发布 SubscriptionTopic 资源,描述事件(资源、触发器,如 create、update、delete 或 FHIRPath 条件,以及允许的过滤器)。订阅者创建一个指向主题的 Subscription,并指定 filterBy 值、channel 类型、endpoint、heartbeat period 和 content 设置(empty、id-only 或 full-resource)。
SubscriptionTopic 是服务器发布的一种资源,用于描述一个事件:涉及哪个资源、哪个触发器(创建、更新、删除或 FHIRPath 条件,例如 %previous.status != 'finished' and %current.status = 'finished') 以及订阅者可以使用哪些过滤器。然后,订阅者创建一个指向该主题的 Subscription:
{
"resourceType": "Subscription",
"status": "requested",
"topic": "http://example.org/fhir/SubscriptionTopic/encounter-end",
"filterBy": [{"resourceType": "Encounter", "filterParameter": "patient", "value": "Patient/123"}],
"channelType": {"system": "http://terminology.hl7.org/CodeSystem/subscription-channel-type", "code": "rest-hook"},
"endpoint": "https://clinic.example.org/hooks/encounters",
"heartbeatPeriod": 60,
"timeout": 30,
"contentType": "application/fhir+json",
"content": "id-only"
}
content 选择传输多少信息:empty(仅事件)、id-only(引用,使用您自己的授权获取其余信息)或 full-resource。heartbeatPeriod 使服务器发送心跳信号,以便检测到静默。
通知的样子
FHIR 订阅通知是一个类型为 subscription-notification 的 Bundle,其第一个条目是 SubscriptionStatus 资源,提供订阅、主题、通知类型(handshake、heartbeat、event-notification、query-status 或 query-event)以及用于检测遗漏事件的 eventsSinceSubscriptionStart 计数器。根据 content 设置,其他条目会携带更改的资源或其引用。
每次通知都是一个类型为 subscription-notification 的 Bundle。它的第一个条目是 SubscriptionStatus,包含订阅引用、主题、通知类型(handshake、heartbeat、event-notification、query-status、query-event)以及一个 eventsSinceSubscriptionStart 计数器;计数器中的间隙表示错过的事件,客户端可以调用 $events 来恢复它。根据 content 的设置,后续条目会携带资源或其引用。
通道:rest-hook(服务器 POST 到您的 HTTPS 端点)、websocket(客户端连接并在套接字上接收通知,适用于浏览器应用)、email(仅通知,不含数据)、message(FHIR 消息 Bundle)。R4 的 sms 通道已被移除。
在生产环境中运行
在生产环境中运行 FHIR 订阅需要:基于事件编号和资源版本进行幂等处理;验证发送者的 endpoint 安全,绝不将 payload 视为授权;容忍包含大量事件的批量 Bundle;对初始握手通知返回 2xx 响应;并意识到许多服务器仍将订阅限制在后端服务而非患者应用。
- 幂等性。 通知在重试后可能会重复;请根据事件编号和资源版本进行键控。
- 安全性。 端点必须验证发送者(共享密钥标头、双向 TLS 或签名),并且绝不能信任有效负载作为授权;当
content为id-only时,请使用您自己的令牌从服务器获取敏感数据。 - 背压。 服务器会批量处理事件并遵守
maxCount;客户端必须接受包含多个事件的 Bundle。 - 握手。 激活时,服务器会发送一个
handshake通知并期望收到 2xx 响应;否则,订阅将转为error状态。 - 范围。 SMART on FHIR 缓慢地增加了订阅范围;许多服务器仍然将订阅限制在后端服务(客户端凭据)而不是患者应用。
非 FHIR 订阅的 Webhook
非 FHIR 订阅的 Webhook 是纯粹的平台机制:您注册一个 HTTPS URL,并接收签名的 JSON 事件,例如资源写入或同意更改,而无需任何 SubscriptionTopic。Anpheros 提供此类 Webhook。它们对于单个平台来说更简单,但无法被通用的 FHIR 客户端发现,因此必须与任何 FHIR 服务器集成的方案应使用 Subscriptions。
包括 Anpheros 在内的许多平台都提供普通的 Webhook:您注册一个 HTTPS URL,然后接收签名的 JSON 事件,例如 资源已写入、同意已更改、文档已最终确定。它们以更少的仪式和没有 SubscriptionTopic 来解决相同的需求,并且它们不是 FHIR 资源,因此通用的 FHIR 客户端无法发现它们。如果您的集成必须与任何 FHIR 服务器配合使用,请使用 Subscriptions;如果它针对的是一个平台,那么该平台的 Webhook 通常更简单。Anpheros 在开发者网站(下方链接)上记录了其 Webhook。
相关页面
来源
- HL7 FHIR R5: Subscription
- HL7 FHIR R5: SubscriptionTopic
- HL7 FHIR R5: SubscriptionStatus and notifications
- HL7 FHIR R4: Subscription
- Subscriptions R5 Backport 实现指南
常见问题
我可以在 R4 服务器上使用 R5 风格的订阅吗?
是的,如果服务器实现了 Subscriptions R5 Backport 实现指南,该指南将主题、过滤器和通道设置编码为 R4 Subscription 资源上的扩展,并使用 R4 Bundle 进行通知。
Subscription 和使用 _lastUpdated 进行轮询之间有什么区别?
轮询会反复询问服务器,不会错过任何内容,但速度慢且效率低下;Subscription 会在事件发生时推送事件。健壮的客户端会结合使用两者:订阅以获得速度,在停机后进行轮询或调用 $events 来恢复。
通知是否包含数据?
仅当 content 为 full-resource 时。更安全的选择是 id-only:通知告诉您哪个资源已更改,然后您使用自己的授权来获取它。
FHIR Subscription 和 Webhook 相同吗?
rest-hook 订阅是一个具有 FHIR 定义形状的 Webhook:可发现的主题、标准的通知 Bundle 和状态跟踪。平台提供的普通 Webhook 仅针对该平台执行相同的任务。
在沙盒中免费试用
5 分钟完成第一次 FHIR 调用. 一个内置患者授权的 HL7 FHIR R4 API:先在沙盒中试用,然后连接您自己的应用或诊所系统。
免费 · 30 位合成患者 · 无需信用卡

