如需使用最新稳定版本,请使用 Spring Integration 7.0.4spring-doc.cadn.net.cn

TCP 消息关联

IP 端点的一个目标是提供与 Spring Integration 应用之外的系统进行通信。 因此,默认情况下只发送和接收消息负载。 从 3.0 版本开始,您可以使用 JSON、Java 序列化或自定义序列化和反序列化器来传输头部信息。 有关更多信息,请参阅 传输头部。 框架本身(服务器端的网关除外)或协作通道适配器不提供消息关联功能。 本文档稍后部分将讨论应用程序可用的各种关联技术。 在大多数情况下,这需要特定于应用级别的消息关联,即使消息负载中包含一些自然的关联数据(如订单号)。spring-doc.cadn.net.cn

网关

网关会自动关联消息。 然而,对于相对低流量的应用,您应该使用出站网关。 当您配置连接工厂以让所有消息对使用单个共享连接('single-use="false"')时,同一时间只能处理一条消息。 新消息必须等待收到前一条消息的回复后才能继续处理。 当连接工厂被配置为每条新消息都使用新连接('single-use="true"')时,此限制将不再适用。 虽然此设置可能比共享连接环境提供更高的吞吐量,但它会带来为每对消息打开和关闭新连接的开销。spring-doc.cadn.net.cn

因此,对于高容量的消息,请考虑使用一对协作的通道适配器。 然而,要实现这一点,您需要提供协作逻辑。spring-doc.cadn.net.cn

另一种解决方案是在 Spring Integration 2.2 中引入的,它使用 CachingClientConnectionFactory,从而允许使用共享连接池。spring-doc.cadn.net.cn

协作外部和内部通道适配器

为了实现高吞吐量(避免使用网关,正如前面提到的),您可以配置一对协作的出站和入站通道适配器。 您也可以使用协作适配器(服务器端或客户端)进行完全异步通信(而不是请求 - 响应语义)。 在服务器端,消息关联由适配器自动处理,因为入站适配器会添加一个头信息,使出站适配器能够确定发送回复消息时使用的连接。spring-doc.cadn.net.cn

在服务器端,您必须填充ip_connectionId头部,因为它用于将消息与连接关联起来。 源自入站适配器的消息会自动设置该头部。 如果您希望构建其他要发送的消息,则需要设置该头部。 您可以从传入的消息中获取该头部的值。

在客户端,应用程序必须提供其自身的关联逻辑(如果需要)。 您可以通过多种方式实现这一点。spring-doc.cadn.net.cn

如果消息负载包含某些自然关联数据(例如事务 ID 或订单号),并且您无需保留原始出站消息中的任何信息(例如回复通道标头),则关联非常简单,无论如何都将在应用层完成。spring-doc.cadn.net.cn

如果消息负载包含某些自然关联数据(如事务 ID 或订单号),但您需要从原始出站消息中保留一些信息(如回复通道头),则可以保留原始出站消息的副本(例如通过使用发布 - 订阅通道),并使用聚合器重新组合必要的数据。spring-doc.cadn.net.cn

对于上述两种场景中的任何一种,如果负载没有天然的相关性数据,您可以在出站通道适配器之前提供一个转换器,以通过此类数据增强负载。 这样的转换器可以将原始负载转换为一个新对象,该对象既包含原始负载,又包含消息头的一个子集。 当然,来自消息头的实时对象(例如回复通道)不能包含在转换后的负载中。spring-doc.cadn.net.cn

如果您选择此类策略,需要确保连接工厂具有适当的序列化器 - 反序列化器对来处理此类负载(例如 DefaultSerializerDefaultDeserializer,它们使用 Java 序列化,或者自定义的序列化器和反序列化器)。 TCP 连接工厂中提到的 ByteArray*Serializer 个选项,包括默认的 ByteArrayCrLfSerializer,除非转换后的负载是 Stringbyte[],否则不支持此类负载。spring-doc.cadn.net.cn

在 2.2 版本发布之前,当协作通道适配器使用客户端连接工厂时,so-timeout 属性默认为默认回复超时时间(10 秒)。 这意味着,如果在此时间段内入站适配器未接收到任何数据,则套接字将被关闭。spring-doc.cadn.net.cn

这种默认行为在真正的异步环境中并不合适,因此现在默认为无限超时。 您可以通过将客户端连接工厂的 so-timeout 属性设置为 10000 毫秒来恢复之前的默认行为。spring-doc.cadn.net.cn

从版本 5.4 开始,多个出站通道适配器和一个 TcpInboundChannelAdapter 可以共享同一个连接工厂。 这使得应用程序能够同时支持请求/回复和任意服务器 → 客户端消息传递。 有关更多信息,请参阅 TCP 网关spring-doc.cadn.net.cn

传递请求头

TCP 是一种流式协议。 SerializersDeserializers 用于界定流中的消息。 在 3.0 版本之前,只有消息负载(Stringbyte[])可以通过 TCP 传输。 从 3.0 版本开始,您不仅可以传输负载,还可以传输选定的头部信息。 然而,像 replyChannel 这样的“实时”对象无法被序列化。spring-doc.cadn.net.cn

通过 TCP 发送头部信息需要一些额外的配置。spring-doc.cadn.net.cn

第一步是提供一个使用mapper属性的MessageConvertingTcpMessageMapper来为ConnectionFactory赋值。 此映射器委托给任何MessageConverter实现,以便将消息转换为可由配置的serializerdeserializer进行序列化和反序列化的对象。spring-doc.cadn.net.cn

Spring Integration 提供了一个 MapMessageConverter,允许指定一组添加到 Map 对象中的头部信息,同时包含有效负载。 生成的 Map 包含两个条目:payloadheadersheaders 条目本身是一个 Map,并包含所选的头部信息。spring-doc.cadn.net.cn

第二步是提供一个序列化和反序列化器,用于在Map和某种 wire 格式之间进行转换。 这可以是一个自定义的SerializerDeserializer,通常当对端系统不是 Spring Integration 应用程序时需要这样做。spring-doc.cadn.net.cn

Spring Integration 提供了一个 MapJsonSerializer,用于在 JSON 和 Map 之间进行转换。 它使用了一个 Spring Integration JsonObjectMapper。 如有需要,您可以提供一个自定义的 JsonObjectMapper。 默认情况下,序列化器会在对象之间插入一个换行符(0x0a)。 有关更多信息,请参阅 Javadocspring-doc.cadn.net.cn

The JsonObjectMapper uses whichever version of Jackson is on the classpath.

您也可以通过使用 DefaultSerializerDefaultDeserializer,对 Map 使用标准的 Java 序列化。spring-doc.cadn.net.cn

下面的示例展示了如何使用 JSON 配置一个连接工厂,以传递 correlationIdsequenceNumbersequenceSize 标头:spring-doc.cadn.net.cn

<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' 的消息,在传输线路上将显示如下:spring-doc.cadn.net.cn

{"headers":{"correlationId":"things","sequenceSize":5,"sequenceNumber":1},"payload":"something"}