发布/订阅camel-netty4

时间:2017-05-26 07:45:58

标签: apache-camel netty tcp-ip

我必须创建一个发布/订阅客户端。 因此,此客户端需要在启动时发送注册调用,之后才会侦听已发布的更新。发布者是第三方软件,只能通过TCP / IP进行通信,因此使用JMS是没有选择的。

我的第一个想法是创建两条路线,一条用于发送请求,另一条用于接收结果。

    // configure clientMode
String rtServerUri = "netty4:tcp://localhost:30600?clientMode=true&decoders=#length-decoder,#string-decoder&encoders=#length-encoder,#string-encoder";

from("quartz://gs/provider?trigger.repeatInterval=15000&trigger.repeatCount=-1")
  .process(exchange -> System.out.println("Trigger registration!"))
  .setBody(constant(registrationBody))
  .to(ExchangePattern.OutOnly, rtServerUri)
;


from(rtServerUri)
  .process(exchange -> System.out.println("Incoming message!"))
  .to("file:test/output?fileName=updates.xml&fileExist=Append")
;

不幸的是,这不起作用,因为建立了两个独立的连接:

Socket connections

有没有人有想法,如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

你是对的,你需要两条路线。但是你不需要同时创建两者。你可以做的是禁用第二条路线,这样它就不会自动启动。然后,一旦第一条路线实际发送了消息,它将触发对第二条路线的呼叫启动。你将有两个我认为不是问题的联系。您只需要在发送注册呼叫后启动监听器。

答案 1 :(得分:0)

我找到了一种似乎对我有用的方法。

解决方案是创建一个扩展NettyComponent的自定义组件。 相应的端点将引用已使用的侦听器通道(Consumer)。

@Override 
protected void doStart() throws Exception 
{ 
  super.doStart(); 

  Field nettyServerBootstrapFactory = GsPblConsumer.class.getSuperclass().getDeclaredField("nettyServerBootstrapFactory"); 
  nettyServerBootstrapFactory.setAccessible(true); 
  Object nsbf = nettyServerBootstrapFactory.get(this); 
  Field channel = nsbf.getClass().getDeclaredField("channel"); 
  channel.setAccessible(true); 
  channelToShare = (Channel) channel.get(nsbf); 
  getEndpoint().setSharedChannel(channelToShare); 
} 

此频道将用于制作人发送消息。

@Override 
public boolean process(Exchange exchange, AsyncCallback callback) 
{ 
  ... 
  // get a channel from the pool 
  Channel existing; 
  try { 
    if (getConfiguration().isShareChannel() && getEndpoint().hasChannelToShare()) 
      existing = getEndpoint().getSharedChannel(); 
    else 
      existing = pool.borrowObject(); 
    if (existing != null) { 
      LOG.trace("Got channel from pool {}", existing); 
    } 
  } catch (Exception e) { 
    exchange.setException(e); 
    callback.done(true); 
    return true; 
  } 

  ... 
} 

如果有人知道更好的解决方案,请告诉我。

netstat

在第一个路由发送请求之后,outOnly将在侦听器处理结果消息后停止。

public class DisableRegisterRoutePolicy extends RoutePolicySupport
{
  @Override
  public void onExchangeDone(Route route, Exchange exchange)
  {
    CamelContext camelContext = exchange.getContext();
    Iterator<InflightRepository.InflightExchange> iterator = camelContext.getInflightRepository().browse().iterator();

    while (iterator.hasNext()) {
      InflightRepository.InflightExchange inflight = iterator.next();

      String id = inflight.getExchange().getExchangeId();
      camelContext.getInflightRepository().remove(inflight.getExchange());
    }

    Route regRoute = camelContext.getRoute("gs-registration-route");
    try
    {
      camelContext.stopRoute(regRoute.getId());
    } catch (Exception e)
    {
      e.printStackTrace();
    }
  }
}

更多细节可以在这里找到:http://camel.465427.n5.nabble.com/publish-subscribe-with-camel-netty4-tp5801431.html

谢谢, Jörg