3 消息(Messages)和管道(channels)

3.1 介绍Spring Integration Messages

Spring Integration的三个基础概念:
- 消息(messages)
- 管道(channels)
- 端点(endpoints)

3.1.1 message里有什么?

消息是一段具体的信息,从一个系统组件发送给其他的系统组件。一段信息指的是(objects, byte arrays, strings, and so forth)。

meta-information : message headers.

基于实现的角色区分三种消息类型:

  • 文档型消息,仅包含信息
  • 命令型消息,指导接收者执行各种操作
  • 事件型消息,that indicate notable occurrences in the system and to which the recipient may react

3.1.2 Spring Integration怎么包装message的

通过一段代码了解Message接口显现什么是消息:

package org.springframework.integration;
public interface Message<T> {
    MessageHeaders getHeaders();
    T getPayload();
}

package org.springframework.integration;
public final class MessageHeaders
implements Map<String, Object>, Serializable {
/* implementation omitted */
}
Message<String> helloMessage =
MessageBuilder.withPayload("Hello, world!")
.setHeader("custom.header", "Value")
.setHeaderIfAbsent("custom.header2", "Value2")
.build();

Message<String> anotherHelloMessage =
MessageBuilder.fromMessage(helloMessage)
.setHeader("custom.header", "ChangedValue")
.setHeaderIfAbsent("custom.header2", "IgnoredValue")
.build();

3.2 介绍Spring Integration Channels

3.2.1 通过channel搬运消息

在Spring Integration, 所有的channels实现MessageChannel接口,后者定义了标准的发消息方法。请注意,这里没有提供接收消息的方法,为什么?
package org.springframework.integration;
public interface MessageChannel {
    boolean send(Message<?> message);
    boolean send(Message<?> message, long timeout);
}

原因是endpoint—polling and subscription 对应了两种迥异的channels类型。

3.2.2 让接收者知道何时收到了消息

SubscribableChannel继承自MessageChannel,当消息来了负责通知订阅者 (subscribers)。

package org.springframework.integration.core;
public interface SubscribableChannel extends MessageChannel {
    boolean subscribe(MessageHandler handler);
    boolean unsubscribe(MessageHandler handler);
}

3.2.3 有没有给我的消息?

另一个是PollableChannel, 需要接收者定期检查有没有消息来。好处是消费者自主决定什么时候处理消息。缺点是需要平衡轮询间隔过长导致延时和轮询频率过短无所获的矛盾。
package org.springframework.integration.core;
public interface PollableChannel extends MessageChannel {
    Message<?> receive();
    Message<?> receive(long timeout);
}

subscription versus polling,选择哪一种?

3.2.4 The right channel for the job

The type of channel you select has significant implications for your application, including transactional boundaries, latency, and overall throughput.

选择什么类型的管道显著地影响应用程序的事务边界,延迟时间和整体吞吐量。

Table 3.1 How do you decide what channel to use?

决定因素

哪些因素必须考虑?

共享上下文(sharing context)

在连续的处理步骤之间,你是否需要传递上下文信息;

当多处地方需要上下文时,可以运用线程本地变量。通过堆栈传递无疑增加了复杂性。

Relying on the thread context is a subtle form of coupling。。。

原子边界(Atomic boundaries)

-有没有原子性的场景?

-经典的例子:银行事务里借记和贷记得同时成功或者失败

典型地用于决定事务边界,得共享上下文。影响线程模型,在挑选channel类型时候限制可用的选项

缓冲消息(Buffering messages)

是否需要考虑可变负载?哪些是即时的,哪些可缓一缓

系统承受高负荷的能力是一个重要的性能因素

阻塞和非阻塞操作(blocking and non blocking operations)

你可以缓存多少消息? 当无法应对需求时该怎么做?

当你的应用无法处理接收到的消息并且没有限制数量,可能会把精力耗在存储代办消息方面。

意识到系统无法兑付需求可能是更好的选项。通用的方法是自我限制接收消息数。

与其处理消息时间过长导致超时或者服务质量下降,不如接收消息然后丢弃它。

消费模型(Consumption Model)

多少组件对接收某消息感兴趣?

有两种范例:点对点和发布-订阅。前者一个消息仅有一个接收者与管道连接,后者消息被所有接收者接收。

如果需求是同一消息被多消费者处理,消费者可以并发工作,采用发布-订阅管道。订机票的例子,请求消息被同时发布给多个provider;

相反的,如果请求消息总是被一个组件处理,支付的例子,你需要点对点策略。

3.2.5 选择channel的样例


Created with Raphaël 2.1.2 A A B B C C chargedBookings emailConfirmationRequests


A: billForBooking Service
B: seatAvailability Service
C: emailConfirmation Service

<channel id="bookingConfirmationRequests"/>
<service-activator input-channel="bookingConfirmationRequests"
output-channel="chargedBookings"
ref="billForBookingService" />
<channel id="chargedBookings" />
<service-activator input-channel="chargedBookings"
output-channel="emailConfirmationRequests"
ref="seatAvailabilityService" />
<channel id="emailConfirmationRequests" />
<outbound-channel-adapter channel="emailConfirmationRequests"
ref="emailConfirmationService" />

In Spring Integration, the default channels are SubscribableChannels, and the message transmission is synchronous.


Created with Raphaël 2.1.2 Sender Sender Receiver Receiver DirectChannel


3.3 渠道合作者 (Channel collaborators)

3.3.1 消息分派

3.3.2 渠道拦截器

4 消息端点(Message Endpoints)

4.2 环绕端点的事务边界

4.2.1 为何共享不全是好事

4.2.2 事务是什么,没有它们可以吗?

4.3 引擎盖之下(under the hood)

4.3.1 端点解析 (Endpoint parsing)

4.3.2 端点实例化 (Endpoint instantiation)

4.4 总结

5 着手去处理业务

5.1 领域驱动转换 (Domain-driven transformation)

5.2 消息驱动服务

5.3 消息发送拦截

5.4 领域驱动消息网关

5.5 链接端点 (Chaining endpoints)

5.6 总结

6 超越顺序处理 : 路由和过滤

6.1 你想接收这个消息吗?

6.2 这是谁的消息?

6.3 引擎之下 (under the hood)

6.4 总结

7 分裂和聚合消息

7.1 介绍相关性

7.2 分裂、聚合和重新排序 (Splitting, aggregating, and resequencing)

7.3 有用的模式

7.4 引擎之下 (under the hood)

7.5 总结