最后更新于2023年8月10日星期四21:27:49 GMT

在过去,交易行为发生在单一领域, 一步一步的, 跟踪请求/响应行为是一项简单的工作. 然而, 今天,对特定域的一个请求可能涉及从起始域到其他域的无数后续异步请求. 例如, 你向Expedia发送请求, 但在幕后,Expedia将你的请求作为消息转发给消息代理. 然后这个信息就会被酒店消费掉, 航空公司和汽车租赁机构也会异步响应. 问题来了, 您的一个请求被传递给众多处理消费者, 我们如何记录这笔交易? 答案是:使用关联ID.

请允许我详细说明.

使用关联ID

关联ID, 也被称为公交ID, 附加到请求和消息的唯一标识符值是否允许引用特定的事务或事件链. 的 关联模式(依赖于Correlation ID的使用)是一个文档完备的企业集成模式. 关联ID被定义为一个非标准的HTTP报头,是HTTP的一部分 Java消息服务(JMS). 但是,将Correlation ID附加到请求是任意的. 你不需要使用它. 但是,如果您正在设计一个包含消息队列和异步处理的分布式系统, 在您的消息中包含关联ID将会做得很好.

下面的图1描述了使用Correlation ID提供显著好处的情况. 图1描述了一个虚构的旅行预订系统,它可以创建酒店, 代表客户租车和预订机票. 客户机可以是一个人,也可以是另一个计算系统.

图1:使用Correlation ID标识分布在多个消息中的单个事务.

图1中描述的系统接受一个请求,该请求描述了三个不同系统之间的预订情况:一个酒店系统, 用于汽车租赁系统和航空公司系统. 上面描述的逻辑流程如下:(1)将请求发送到请求处理程序,请求处理程序将请求中的信息转换为三条消息. (2)将一条描述酒店预订参数的消息发送到专门用于酒店预订消息的消息队列. 另一条描述汽车租赁的消息被发送到汽车租赁消息队列. 描述航空公司预订的第三条消息被发送到航空公司预订队列. (3)每个预订服务专用的微服务正在监听相关队列的传入消息. 微服务从其队列中检索消息, 完成它的工作,并随着工作的进行将信息记录到日志服务(4). 当微服务完成它的工作时, 预订结果作为消息发送到响应队列(5)。. 响应处理程序从响应队列中提取消息,并在检索到与给定预订相关的所有三个预期响应消息时提取消息, (6)响应处理程序将三个预订消息中的信息聚合为对请求者的单个响应.

最突出的问题是, 给定在给定响应队列上发生的所有消息活动, 响应处理程序如何知道哪个响应消息与给定的预订相关? 这就是相关性ID发挥作用的地方.

分配一个CorrelationID

正如您刚刚了解到的,关联ID是将消息绑定到事务的唯一标识符. 在本例中,事务是对酒店的预订请求的组合, 汽车租赁和航空公司微服务. 在我们的场景中, 请求处理程序创建并分配一个Correlation ID,然后将单个请求拆分为三个发送到各自消息队列的后续消息. (请参见下面的图2.)

图2:在分布式系统中需要使用消息头之前,为消息头创建并分配一个CorrelationID.


按照惯例,在请求或消息的标头中传递关联ID. 在报头中使用的常用但非标准的字段名是X-Correlation-ID. 下面的图3显示了如何将Correlation ID传播到发送到每个预订微服务的后续消息中.

图3:在多个消息上使用CorrelationID协调消息活动

进入每个不同预订队列的消息将在header中插入Correlation id., 如果后续消息传播发生,处理来自预订队列的这些消息的微服务中的智能将向下游移动给定的Correlation ID. 此外,微服务将在生成的任何日志条目中包含关联ID. 当涉及到日志记录, 关联ID将是将事务信息粘合在一起的粘合剂.

关联ID在何时何地分配?

一个好的经验法则是:

尽可能快地分配关联ID. 并且,如果您发现传递给您一个Correlation ID,请使用它.

使用日志中的关联ID

当涉及到日志活动时,关联id特别强大. 如前所述,CorrelationID是将事务信息粘合在一起的粘合剂. 您可能还记得我们在上面图1中的讨论, 预订微服务所做的部分工作是将事件活动记录到公共日志服务,例如 Logentries. 提供带有日志条目的CorrelationID提供了一个键,通过该键可以实现审计. 请记住,微服务将处理数千条消息. 微服务唯一知道的是它处理的消息中传递的信息. 微服务只是没有看到大局. 这就是为什么它们被称为微服务. 它们一次处理一条消息. 这些信息是如何与其他事物联系在一起的. 理解诸如上下文和审计跟踪之类的事情是日志的工作. 日志记录是相关性ID变得无价的地方.

请记住,上面图1中描述的系统架构将每个微服务写入一个公共日志服务. 因此,如果出现问题,我们要做的第一件事就是查看日志. 如果我们能找到的话,我们需要的所有信息都在那里. 在事件日志中包含关联ID将工作流或事务绑定在一起. 在系统出现故障的情况下, 我们所需要做的就是根据关联ID查询日志,以统一了解正在运行的各种微服务之间的事务活动. 然后,对事件有了统一的认识,我们就可以确定可能的原因. 如果我们没有关联ID, 理解事件的进程会更加困难, 也许无法确定.

如何在HTTP请求中使用CorrelationID?

在企业系统中,越来越多的趋势是检查传入请求和传入请求的报头中是否存在关联ID, 相关性ID应该存在吗, 然后在服务器端向下传播提交的CorrelationID. So, 如果您正在编写客户端代码并希望使服务器知道关联ID, 将其包含在HTTP请求的标头中, 但是是非标准的字段名, X-Correlation-ID.

把它们放在一起

关联ID的概念很简单. 该值对于给定事务中的所有请求、消息和响应都是通用的. 通过这种简单性,您可以获得很多功能.

异步编程本质上是很难跟踪的. 不能保证事件的先后顺序. 事情该发生的时候就会发生,有时更早,有时更晚,有时根本不会发生. 在事务中的元素之间使用一个公共的“标记”,可以使用一个公共的引用,通过这个引用可以进行日志记录和审计. 当异步系统出现问题时, 分布式系统, 故障排除不仅仅是将日志中的时间戳拼凑在一起. 在请求和消息中包含关联ID,并输入关联ID作为日志记录的标准实践的一部分, 提供所需的粘合剂,以创建连贯的, 可理解的事件审计.

当您可以将事务的事件分组在统一值下时, 关联ID, 你可以把时间花在解决问题而不是发现问题上. 没有关联ID, 有一种说法, 如果你把一只黑猩猩永远放在打字机前, 最终,这只动物会打出哈姆雷特.这同样适用于没有关联ID的日志记录, 只是我们都不会永远在这里. 使用关联ID. 你会很高兴这么做的.

   

不要错过任何一个博客

   

获取有关安全的最新故事、专业知识和新闻.