服务之间异步通信的最佳实践

Posted

技术标签:

【中文标题】服务之间异步通信的最佳实践【英文标题】:Best practice for async communication between services 【发布时间】:2012-04-12 16:07:56 【问题描述】:

以下场景中最好/好的服务绑定/通信实践是什么(希望标题有点意思):

一个业务层 (BL) 包含多个服务方法,这些服务方法共享(作为公共通信端点)一个异步套接字服务 (SS),该服务可能被这些方法绑定并用于套接字 IO。

例如BL 抓取 SL 并调用 send(message) 然后等待响应。

我一开始使用回调和活页夹模式。由于我在使用活页夹模式进行清晰设计时遇到了一些问题(缺少消息队列并且一切都在主线程中完成),我现在正在尝试消息模式。

所以基本上,BL 服务和 SL 服务现在都有一个 Messenger 和一个相应的处理程序:

private final IncomingHandler incomingHandler = new IncomingHandler();
private final Messenger messengerReceiver = new Messenger(incomingHandler);
private class IncomingHandler extends Handler 
  @Override
  public void handleMessage(Message msg) 
  ...
  

其中一个 BL 是 AbstractAccountAuthenticator 子类实现

addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options)
     ...
     if(socketConnectionState != null)
        Bundle authBundle = new Bundle();
        authBundle.putString("password", password);
        authBundle.putString("username", account.name);
        Message message = Message.obtain(null, SocketConnectionHandler.SEND_REQUEST, authBundle);
        message.replyTo = messengerReceiver;
        socketConnectionState.getMessenger().send(message);
...

它也使用 SL 来获取 authToken。 addAccount() 方法要么要求立即在 Bundle 中返回结果(authToken),要么调用响应回调方法。 现在,如果我通过 SL 请求 addAccount 中的身份验证令牌,我将如何处理以传回结果?

这里的主要问题是结果没有返回到调用方法(addAccount()),而是返回到 messengerReceiver 处理程序。

我能想到的唯一方法是 BlockingQueue,它由消息处理程序提供响应,然后在 addAccount() 方法中获取,但这真的感觉非常难看。 其他想法?方法是否正确?

【问题讨论】:

【参考方案1】:

您的问题只有在您陈述前提时才会出现,即响应是消息处理程序的关注点。

我最近在工作中遇到了同样的问题。我们通过扩展消息处理程序的参数列表来解决它

public interface MessageHandler 
    public void receivedMessage(Message message, ResponseChannel channel);


interface ResponseChannel 
    public void respond(Message response);


interface Message 

当然可以在MessageHandler 的每个实例中引入一个成员变量,但这会消除无状态 - 最后,两种方法背后的原理是相同的。

不过,还有另一种可能性。

关注点分离

正如我在分配回答消息处理程序响应的额外责任之前所说的那样,这会留下不好的味道。 消息处理程序已经负责接收传入的消息。

他处理传入的消息,这应该是提取相关参数并将消息转发给相关方或在模型或控制器上调用适当方法的简短过程。

这应该是一个简短且非详尽的过程,因为消息处理程序在逻辑上不是发送/接收组件的一部分,而是在那里注册并与所有其他消息处理程序及其调用共享一个线程或线程池。

那么应该如何处理响应呢?因此,如果不是处理程序的责任,则处理程序通知的各方应采取行动。

public interface MessageHandler 
    public void receivedMessage(Message message, ApplicationContext context);


interface ApplicationContext 
    public void notifyUserJoined(String name);


interface Message 
    public String getUser();

【讨论】:

以上是关于服务之间异步通信的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

使用 PhoneGap/Cordova 时应用程序和服务器之间通信的最佳实践

在片段和活动之间进行通信 - 最佳实践

在 Rust 程序和嵌入式 WebAssembly 运行时之间进行通信的最佳实践是啥?

RabbitMQ实战:消息通信模式和最佳实践

Consul 快速入门 - Kong最佳实践

结合异步模型,再次总结Netty多线程编码最佳实践