TCP 消息关联
网关
网关会自动关联消息。 但是,您应该对相对较少的应用程序使用出站网关。 当您将连接工厂配置为对所有消息对使用单个共享连接 ('single-use=“false”') 时,一次只能处理一条消息。 新消息必须等待,直到收到对上一条消息的回复。 当为每个新消息配置连接工厂以使用新连接 ('single-use=“true”') 时,此限制不适用。 虽然此设置可以提供比共享连接环境更高的吞吐量,但它会带来为每个消息对打开和关闭新连接的开销。
因此,对于高容量消息,请考虑使用一对协作的通道适配器。 但是,为此,您需要提供协作逻辑。
Spring Integration 2.2 中引入的另一种解决方案是使用CachingClientConnectionFactory
,这允许使用共享连接池。
协作出站和入站通道适配器
为了实现高容量吞吐量(如前所述,避免使用网关的陷阱),您可以配置一对协作的出站和入站通道适配器。 您还可以使用协作适配器(服务器端或客户端)进行完全异步的通信(而不是使用请求-答复语义)。 在服务器端,消息关联由适配器自动处理,因为入站适配器添加了一个 Headers,允许出站适配器在发送回复消息时确定要使用的连接。
在服务器端,您必须填充ip_connectionId header,因为它用于将消息关联到连接。
源自入站适配器的消息会自动设置 Header。
如果您希望构造要发送的其他消息,则需要设置 header。
您可以从传入消息中获取标头值。 |
在客户端,应用程序必须根据需要提供自己的关联逻辑。 您可以通过多种方式执行此作。
如果消息有效负载具有一些自然关联数据(例如交易 ID 或订单号),并且您不需要保留原始出站消息中的任何信息(例如回复通道标头),则关联很简单,并且在任何情况下都将在应用程序级别完成。
如果消息负载具有一些自然关联数据(例如事务 ID 或订单号),但您需要保留原始出站消息中的一些信息(例如回复通道标头),则可以保留原始出站消息的副本(可能通过使用发布-订阅通道)并使用聚合器重新组合必要的数据。
对于前两种情况中的任何一种,如果有效负载没有自然关联数据,则可以在出站通道适配器的上游提供一个转换器,以使用此类数据增强有效负载。 此类转换器可以将原始有效负载转换为包含原始有效负载和消息标头的某些子集的新对象。 当然,来自 Headers 的 Live Objects(例如回复通道)不能包含在转换后的有效负载中。
如果你选择这样的策略,你需要确保连接工厂有一个适当的 serializer-deserializer 对来处理这样的有效负载(例如DefaultSerializer
和DefaultDeserializer
,它们使用 Java 序列化,或者自定义序列化器和反序列化器)。
这ByteArray*Serializer
TCP Connection Factories 中提到的选项,包括默认的ByteArrayCrLfSerializer
不支持此类负载,除非转换后的负载是String
或byte[]
.
在 2.2 发行版之前,当协作通道适配器使用客户端连接工厂时, 此默认行为在真正的异步环境中不适用,因此它现在默认为无限超时。
您可以通过设置 |
从版本 5.4 开始,多个出站通道适配器和一个TcpInboundChannelAdapter
可以共享相同的连接工厂。
这允许应用程序同时支持请求/回复和任意服务器→客户端消息收发。
有关更多信息,请参阅 TCP 网关。
传输标头
TCP 是一种流协议。Serializers
和Deserializers
在流中划分消息。
在 3.0 之前,只有消息负载 (String
或byte[]
) 可以通过 TCP 传输。
从 3.0 开始,您可以传输选定的标头以及有效负载。
但是,“活动”对象(例如replyChannel
标头,无法序列化。
通过 TCP 发送标头信息需要一些额外的配置。
第一步是提供ConnectionFactory
替换为MessageConvertingTcpMessageMapper
,它使用mapper
属性。
此映射器将委托给任何MessageConverter
实现将消息与某个对象相互转换,这些对象可以由配置的serializer
和deserializer
.
Spring 集成提供了一个MapMessageConverter
,它允许指定添加到Map
对象以及有效负载。
生成的 Map 有两个条目:payload
和headers
.
这headers
entry 本身是一个Map
并包含选定的标题。
第二步是提供一个序列化器和一个反序列化器,它们可以在Map
和一些 wire 格式。
这可以是自定义的Serializer
或Deserializer
,如果对等系统不是 Spring 集成应用程序,您通常需要它。
Spring 集成提供了一个MapJsonSerializer
要将Map
到 JSON 和从 JSON 返回。
它使用 Spring 集成JsonObjectMapper
.
您可以提供自定义JsonObjectMapper
如果需要。
默认情况下,序列化程序会插入换行符 (0x0a
) 字符。
有关更多信息,请参阅 Javadoc。
这JsonObjectMapper 使用任何版本的Jackson 位于 Classpath 上。 |
您还可以使用Map
,通过使用DefaultSerializer
和DefaultDeserializer
.
以下示例显示了一个连接工厂的配置,该工厂将correlationId
,sequenceNumber
和sequenceSize
headers 的调用:
<int-ip:tcp-connection-factory id="client"
type="client"
host="localhost"
port="12345"
mapper="mapper"
serializer="jsonSerializer"
deserializer="jsonSerializer"/>
<bean id="mapper"
class="o.sf.integration.ip.tcp.connection.MessageConvertingTcpMessageMapper">
<constructor-arg name="messageConverter">
<bean class="o.sf.integration.support.converter.MapMessageConverter">
<property name="headerNames">
<list>
<value>correlationId</value>
<value>sequenceNumber</value>
<value>sequenceSize</value>
</list>
</property>
</bean>
</constructor-arg>
</bean>
<bean id="jsonSerializer" class="o.sf.integration.ip.tcp.serializer.MapJsonSerializer" />
使用上述配置发送的有效负载为 'something' 的消息将出现在网络上,如下所示:
{"headers":{"correlationId":"things","sequenceSize":5,"sequenceNumber":1},"payload":"something"}