Cliente síncrono Netty com chamadores assíncronos

Estou criando um servidor que consome comandos de várias fontes, como JMS, SNMP, HTTP etc. Tudo isso é assíncrono e funciona bem. O servidor mantém uma única conexão com um único item de hardware herdado que possui uma arquitetura de solicitação / resposta com um protocolo TCP personalizado. Idealmente, eu gostaria de um único comando como este método de tipo de bloqueio

public Response issueCommandToLegacyHardware(Command command)

ou este método de tipo assíncrono

public Future<Response> issueCommandToLegacyHardware(Command command)

Eu sou relativamente novo na programação Netty e assíncrona, basicamente aprendendo-a à medida que avança. Meu pensamento atual é que meuLegacyHardwareClient aula terápublic synchronized issueCommandToLegacyHardware(Command command), gravará no canal do cliente o hardware herdado e, em seguida,take() a partir de umSynchronousQueue<Response> o que irá bloquear. O ChannelInboundHandler no pipeline seráoffer() a Response aoSynchronousQueue>Response> o que permitirá que otake() para desbloquear e receber os dados.

Isso é muito complicado? Existem exemplos em torno de implementações síncronas de clientes Netty que eu posso olhar? Existem práticas recomendadas para o Netty? Obviamente, eu poderia usar soquetes Java padrão, no entanto, o poder do Netty para analisar protocolos personalizados e a facilidade de manutenção são grandes demais para desistir.

UPDATE: Apenas em relação à implementação, usei um ArrayBlockingQueue <> () e usei put () e remove () em vez de offer () e remove (). Porque eu queria garantir que as solicitações subsequentes ao hardware herdado fossem enviadas apenas quando quaisquer solicitações ativas tivessem sido respondidas, pois o comportamento do hardware herdado não é conhecido com certeza de outra forma.

A razão pela qual offer () e remove () não funcionou para mim foi que o comando offer () não passaria nada se não houvesse uma solicitação take () de bloqueio ativo no outro lado. O inverso é verdade que remove () não retornaria nada, a menos que houvesse uma chamada put () de bloqueio inserindo dados. Não pude usar um put () / remove (), pois a instrução remove () nunca seria alcançada, pois não havia nenhuma solicitação gravada no canal para acionar o evento a partir do qual o remove () seria chamado. Não pude usar offer () / take (), pois a instrução offer () retornaria falsa, pois a chamada take () ainda não havia sido executada. Usando o ArrayBlockingQueue <> () com capacidade de 1, garantiu que apenas um comando pudesse ser executado ao mesmo tempo. Quaisquer outros comandos seriam bloqueados até que houvesse espaço suficiente para inserir, com uma capacidade de 1, isto significava que tinha que estar vazio. O esvaziamento da fila foi feito depois que uma resposta foi recebida do hardware herdado. Isso garantiu um bom comportamento síncrono em relação ao hardware herdado, mas forneceu uma API assíncrona aos usuários do hardware herdado, para o qual existem muitos.

questionAnswers(1)

yourAnswerToTheQuestion