Java TCP Spring集成-Dispatcher没有';答复';频道
我使用SpringIntegration通过提供一些消息并获得响应来对服务器进行TCP调用。我更喜欢使用通道适配器发送和接收批量消息。我面临的问题是响应通道。获取响应通道的“Dispatcher没有通道订户”。 除了没有在响应通道上传输响应外,其他一切都正常工作。我可以看到服务器上的握手和日志中的响应被放在响应和记录器通道上。但在抛出异常之后。配置设置为:Java TCP Spring集成-Dispatcher没有';答复';频道,java,spring,spring-integration,Java,Spring,Spring Integration,我使用SpringIntegration通过提供一些消息并获得响应来对服务器进行TCP调用。我更喜欢使用通道适配器发送和接收批量消息。我面临的问题是响应通道。获取响应通道的“Dispatcher没有通道订户”。 除了没有在响应通道上传输响应外,其他一切都正常工作。我可以看到服务器上的握手和日志中的响应被放在响应和记录器通道上。但在抛出异常之后。配置设置为: <gateway id="clientPositionsGateway" service-interface="com.example
<gateway id="clientPositionsGateway" service-interface="com.example.ClientPositionsGateway">
<method name="fetchClientPositions" request-channel="clientPositionsRequestChannel" reply-channel="dmQueryResponseChannel"/>
</gateway>
<channel id="clientPositionsRequestChannel" />
<splitter input-channel="clientPositionsRequestChannel"
output-channel="singleClientPositionsRequestChannel" />
<channel id = "singleClientPositionsRequestChannel" />
<transformer
input-channel="singleClientPositionsRequestChannel"
output-channel="dmQueryRequestChannel"
ref="dmPosBaseQueryTransformer" />
<logging-channel-adapter channel="clientBytes2StringChannel"/>
<channel id = "dmQueryRequestChannel">
<dispatcher task-executor="executor"/>
</channel>
<ip:tcp-connection-factory id="csClient"
type="client"
host="serverHost"
port="22010"
single-use="true"
deserializer="connectionSerializeDeserialize"
/>
<ip:tcp-outbound-channel-adapter id="dmServerOutboundAdapter"
channel="dmQueryRequestChannel"
connection-factory="csClient"
/>
<ip:tcp-inbound-channel-adapter id="dmServerInboundAdapter"
channel="dmQueryResponseChannel"
connection-factory="csClient"
error-channel="errorChannel"/>
<transformer input-channel="dmQueryResponseChannel" output-channel="clientBytes2StringChannel" ref="dmPOSBaseQueryResponseTransformer"
/>
<channel id="dmQueryResponseChannel"/>
<channel id="clientBytes2StringChannel"/>
正如Artem在评论中所说,“Dispatcher没有订阅者”在这里意味着没有端点配置为在
dmQueryResponseChannel
上接收响应,或者将该信道配置为其输入信道的端点没有启动
<gateway id="clientPositionsGateway" service-interface="com.example.ClientPositionsGateway">
<method name="fetchClientPositions" request-channel="clientPositionsRequestChannel" reply-channel="dmQueryResponseChannel"/>
</gateway>
<channel id="clientPositionsRequestChannel" />
<splitter input-channel="clientPositionsRequestChannel"
output-channel="singleClientPositionsRequestChannel" />
<channel id = "singleClientPositionsRequestChannel" />
<transformer
input-channel="singleClientPositionsRequestChannel"
output-channel="dmQueryRequestChannel"
ref="dmPosBaseQueryTransformer" />
<logging-channel-adapter channel="clientBytes2StringChannel"/>
<channel id = "dmQueryRequestChannel">
<dispatcher task-executor="executor"/>
</channel>
<ip:tcp-connection-factory id="csClient"
type="client"
host="serverHost"
port="22010"
single-use="true"
deserializer="connectionSerializeDeserialize"
/>
<ip:tcp-outbound-channel-adapter id="dmServerOutboundAdapter"
channel="dmQueryRequestChannel"
connection-factory="csClient"
/>
<ip:tcp-inbound-channel-adapter id="dmServerInboundAdapter"
channel="dmQueryResponseChannel"
connection-factory="csClient"
error-channel="errorChannel"/>
<transformer input-channel="dmQueryResponseChannel" output-channel="clientBytes2StringChannel" ref="dmPOSBaseQueryResponseTransformer"
/>
<channel id="dmQueryResponseChannel"/>
<channel id="clientBytes2StringChannel"/>
在任何情况下,即使您解决了这个问题,为请求/响应场景使用独立的适配器也是很棘手的,因为框架无法自动将响应与请求关联起来。这就是出站网关的用途。您可以使用协作适配器,但必须自己处理相关性。如果您正在使用请求/应答网关来启动流,则必须使用中探讨的技术。这是因为使用独立适配器意味着您将丢失用于将响应返回网关的replyChannel
头
<gateway id="clientPositionsGateway" service-interface="com.example.ClientPositionsGateway">
<method name="fetchClientPositions" request-channel="clientPositionsRequestChannel" reply-channel="dmQueryResponseChannel"/>
</gateway>
<channel id="clientPositionsRequestChannel" />
<splitter input-channel="clientPositionsRequestChannel"
output-channel="singleClientPositionsRequestChannel" />
<channel id = "singleClientPositionsRequestChannel" />
<transformer
input-channel="singleClientPositionsRequestChannel"
output-channel="dmQueryRequestChannel"
ref="dmPosBaseQueryTransformer" />
<logging-channel-adapter channel="clientBytes2StringChannel"/>
<channel id = "dmQueryRequestChannel">
<dispatcher task-executor="executor"/>
</channel>
<ip:tcp-connection-factory id="csClient"
type="client"
host="serverHost"
port="22010"
single-use="true"
deserializer="connectionSerializeDeserialize"
/>
<ip:tcp-outbound-channel-adapter id="dmServerOutboundAdapter"
channel="dmQueryRequestChannel"
connection-factory="csClient"
/>
<ip:tcp-inbound-channel-adapter id="dmServerInboundAdapter"
channel="dmQueryResponseChannel"
connection-factory="csClient"
error-channel="errorChannel"/>
<transformer input-channel="dmQueryResponseChannel" output-channel="clientBytes2StringChannel" ref="dmPOSBaseQueryResponseTransformer"
/>
<channel id="dmQueryResponseChannel"/>
<channel id="clientBytes2StringChannel"/>
或者,您可以使用一个void returning网关来发送请求,并使用一个
,这样框架将使用响应回调,您可以通过编程方式进行自己的关联。配置设置:
<gateway id="clientPositionsGateway" service-interface="com.example.ClientPositionsGateway">
<method name="fetchClientPositions" request-channel="clientPositionsRequestChannel" reply-channel="dmQueryResponseChannel"/>
</gateway>
<channel id="clientPositionsRequestChannel" />
<splitter input-channel="clientPositionsRequestChannel"
output-channel="singleClientPositionsRequestChannel" />
<channel id = "singleClientPositionsRequestChannel" />
<transformer
input-channel="singleClientPositionsRequestChannel"
output-channel="dmQueryRequestChannel"
ref="dmPosBaseQueryTransformer" />
<logging-channel-adapter channel="clientBytes2StringChannel"/>
<channel id = "dmQueryRequestChannel">
<dispatcher task-executor="executor"/>
</channel>
<ip:tcp-connection-factory id="csClient"
type="client"
host="serverHost"
port="22010"
single-use="true"
deserializer="connectionSerializeDeserialize"
/>
<ip:tcp-outbound-channel-adapter id="dmServerOutboundAdapter"
channel="dmQueryRequestChannel"
connection-factory="csClient"
/>
<ip:tcp-inbound-channel-adapter id="dmServerInboundAdapter"
channel="dmQueryResponseChannel"
connection-factory="csClient"
error-channel="errorChannel"/>
<transformer input-channel="dmQueryResponseChannel" output-channel="clientBytes2StringChannel" ref="dmPOSBaseQueryResponseTransformer"
/>
<channel id="dmQueryResponseChannel"/>
<channel id="clientBytes2StringChannel"/>
<gateway id="clientPositionsGateway" service-interface="com.example.ClientPositionsGateway">
<method name="fetchClientPositions" request-channel="clientPositionsRequestChannel" reply-channel="dmQueryResponseChannel"/>
</gateway>
<channel id="clientPositionsRequestChannel" />
<splitter input-channel="clientPositionsRequestChannel"
output-channel="singleClientPositionsRequestChannel" />
<channel id = "singleClientPositionsRequestChannel" />
<transformer
input-channel="singleClientPositionsRequestChannel"
output-channel="dmQueryRequestChannel"
ref="dmPosBaseQueryTransformer" />
<logging-channel-adapter channel="clientBytes2StringChannel"/>
<channel id = "dmQueryRequestChannel">
<dispatcher task-executor="executor"/>
</channel>
<ip:tcp-connection-factory id="csClient"
type="client"
host="serverHost"
port="22010"
single-use="true"
deserializer="connectionSerializeDeserialize"
/>
<ip:tcp-outbound-channel-adapter id="dmServerOutboundAdapter"
channel="dmQueryRequestChannel"
connection-factory="csClient"
/>
<ip:tcp-inbound-channel-adapter id="dmServerInboundAdapter"
channel="dmQueryResponseChannel"
connection-factory="csClient"
error-channel="errorChannel"/>
<transformer input-channel="dmQueryResponseChannel" output-channel="clientBytes2StringChannel" ref="dmPOSBaseQueryResponseTransformer"
/>
<channel id="dmQueryResponseChannel"/>
<channel id="clientBytes2StringChannel"/>
公共接口客户端位置网关{
字符串fetchClientPositions(列表clientList);
}
以下是解决我问题的代码:
<gateway id="clientPositionsGateway" service-interface="com.example.ClientPositionsGateway">
<method name="fetchClientPositions" request-channel="clientPositionsRequestChannel" reply-channel="dmQueryResponseChannel"/>
</gateway>
<channel id="clientPositionsRequestChannel" />
<splitter input-channel="clientPositionsRequestChannel"
output-channel="singleClientPositionsRequestChannel" />
<channel id = "singleClientPositionsRequestChannel" />
<transformer
input-channel="singleClientPositionsRequestChannel"
output-channel="dmQueryRequestChannel"
ref="dmPosBaseQueryTransformer" />
<logging-channel-adapter channel="clientBytes2StringChannel"/>
<channel id = "dmQueryRequestChannel">
<dispatcher task-executor="executor"/>
</channel>
<ip:tcp-connection-factory id="csClient"
type="client"
host="serverHost"
port="22010"
single-use="true"
deserializer="connectionSerializeDeserialize"
/>
<ip:tcp-outbound-channel-adapter id="dmServerOutboundAdapter"
channel="dmQueryRequestChannel"
connection-factory="csClient"
/>
<ip:tcp-inbound-channel-adapter id="dmServerInboundAdapter"
channel="dmQueryResponseChannel"
connection-factory="csClient"
error-channel="errorChannel"/>
<transformer input-channel="dmQueryResponseChannel" output-channel="clientBytes2StringChannel" ref="dmPOSBaseQueryResponseTransformer"
/>
<channel id="dmQueryResponseChannel"/>
<channel id="clientBytes2StringChannel"/>
@ContextConfiguration(locations={"/clientGIM2Position.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class GetClientPositionsTest {
@Autowired
ClientPositionsGateway clientPositionsGateway;
@Test
public void testGetPositions() throws Exception {
String positions = clientPositionsGateway.fetchClientPositions(clientList);
System.out.println("returned !!!!" + positions);
}
}
如果从客户端线程调用您的clientPositionsGateway,则没有理由使用执行器通道。如果您不使用clientPositionsGateway,请尝试使用Future gateway:并再次尝试:不使用executor通道。我看不出在两个网关上都使用
回复频道的理由。
还有一个:在
之前有
,但是
之后的
在哪里?。。
在您当前的情况下,您将从您的客户位置Gateway获得回复,所有其他回复将被删除,因为临时回复频道将被关闭。请显示“dmQueryRequestChannel”订户的配置。试试这个
17:23:30.347[pool-1-thread-1]调试o.s.i.i.t.c.TcpNetConnection-收到消息[Payload=CLIENT_ID | MANAGER | HOLD|TYPE AAAIH | CURR][Headers={timestamp=1379678010347,id=c51a97ab-0fc6-4270-bdda-46a91e0d102e,ip_-tcp_-remotePort=22010,ip_-address=hostaddress,ip_-hostname=hostname,ip_-connectionId=hostname:22010:93360e5b-82f8-4e06-906A5989D0D583}]17:23:30.347[pool-1-thread-1]调试o.s.i.channel.ExecutorChannel-在通道“DmyResponseChannel”上显示消息:[Payload=CLIENT|ID|MANAGER|HOLD|TYPE AAAIH|CURR][Headers={timestamp=1379678010347,ID=c51a97ab-0fc6-4270-bdda-46a91e0d102e,ip|tcp|remotePort=22010,ip|address=hostaddress,ip|hostname=hostname,ip|connectionId=hostname:22010:93360e5b-82f8-4e06-906a-6A5989d583]17:30.347[executor-1]DEBUG o.s.b.f.s.DefaultListableBeanFactory-返回单例bean'errorChannel'的缓存实例17:23:30.347[executor-1]DEBUG o.s.i.c.PublishSubscribeChannel-在通道'errorChannel'上呈现,消息:[有效负载=org.springframework.integration.MessageDispatchingException:Dispatcher没有订阅者][标头={timestamp=1379678010347,id=5cdcae44-e874-4ad2-af47-4f9b91a8cdde}]17:23:30.347[executor-1]调试o.s.i.handler.LoggingHandler-(内部bean)#2收到的消息:[有效负载=org.springframework.integration.MessageDispatchingException:Dispatcher没有订户][头={timestamp=1379678010347,id=5CDAE44-e874-4ad2-af47-4F9B918CDDE}]你要回答我的问题吗?我明白什么。我的意思是可能没有“dmQueryResponseChannel”的订户或者它没有启动即使我使用的是void returning gateway,消息也不会流到服务器。另外,使用出站网关也会引发相同的异常。Quiet对如何将响应与请求通道关联感到困惑!!!我没有使用协作适配器模型吗?您需要显示所有配置的上游和下游组件,例如,我们需要查看您的回复通道连接到哪个端点。使用该配置,您有两个订阅服务器到dmQueryResponseChannel
;转换器和入站网关。在转换器之后,您有一个简单的日志适配器。回复将是日志记录器wil发送的循环分布式消息我从未到达网关。但是,正如我所说的,此配置将永远无法工作,因为您无法发送任意异步回复(例如由入站适配器接收)到网关回复通道-您必须还原replyChannel标头。请使用出站网关重试,显示新配置,并显示完整日志。此操作已成功运行:)非常感谢你们Gary和Artem:)只想知道使用此配置可以实现数百万条消息的并行处理吗?很高兴首先,你理解了网关的概念;-)!关于并行性:你真的确定你的环境可能支持百万个线程吗?;-)或者换句话说:你的机器有百万个CPU内核吗?对不起,我不是说有百万个线程。我只是想问一下这个设计是否适合
<gateway id="clientPositionsGateway" service-interface="com.example.ClientPositionsGateway">
<method name="fetchClientPositions" request-channel="clientPositionsRequestChannel" reply-channel="dmQueryResponseChannel"/>
</gateway>
<channel id="clientPositionsRequestChannel" />
<splitter input-channel="clientPositionsRequestChannel"
output-channel="singleClientPositionsRequestChannel" />
<channel id = "singleClientPositionsRequestChannel" />
<transformer
input-channel="singleClientPositionsRequestChannel"
output-channel="dmQueryRequestChannel"
ref="dmPosBaseQueryTransformer" />
<logging-channel-adapter channel="clientBytes2StringChannel"/>
<channel id = "dmQueryRequestChannel">
<dispatcher task-executor="executor"/>
</channel>
<ip:tcp-connection-factory id="csClient"
type="client"
host="serverHost"
port="22010"
single-use="true"
deserializer="connectionSerializeDeserialize"
/>
<ip:tcp-outbound-channel-adapter id="dmServerOutboundAdapter"
channel="dmQueryRequestChannel"
connection-factory="csClient"
/>
<ip:tcp-inbound-channel-adapter id="dmServerInboundAdapter"
channel="dmQueryResponseChannel"
connection-factory="csClient"
error-channel="errorChannel"/>
<transformer input-channel="dmQueryResponseChannel" output-channel="clientBytes2StringChannel" ref="dmPOSBaseQueryResponseTransformer"
/>
<channel id="dmQueryResponseChannel"/>
<channel id="clientBytes2StringChannel"/>