メッセージルーティングのスケーラブルな実装

I.はじめに

最近、WeChatアプレットを実装する場合、WeChatサーバーからプッシュされたさまざまなメッセージを処理する必要があります。メッセージには、サブスクリプションメッセージ、グラフィックメッセージなど、さまざまな種類があります。偉大な神々のいくつかのデザインパターンから学んだ後、単純なメッセージルーティングモデルが実装されます。これは、複数のタイプのメッセージ、複数のルーティングマッチング、および複数のメッセージ処理に対応できます。

二、モデル

image.png

  • メッセージ自体にはいくつかの特徴的な量があり、メッセージルーティングルールを照合するための基礎として使用できます。

  • メッセージルーターには、複数のメッセージルーティングルールが含まれています。

  • メッセージルーティングルールには、インターセプター、マッチャー、および複数のプロセッサーが含まれます。

三、コード

3.1メッセージの定義

ソースコード:https//segmentfault.com/a/1190000039689926

消費されるメッセージ

@Builder
@Getter
@ToString
public class Message {
    private String event;
    private String msgType;
    private String content;
    private String fromUser;
    private String toUser;
    private Instant createTime;
    //... as you wish
}

消費者の情報は、オブジェクトが多数含まれていなければTraitなどの分野を、eventmsgTypecontentこれらのフィールドは、ルーティングルールを照合するための基礎としてだけでなく、特定のメッセージを処理するための条件としても使用できます。さまざまな業種に応じて拡張できます。

メッセージ処理結果

@Builder
@ToString
public class OutMessage {
    private String msgType;
    private String fromUser;
    private String toUser;
    private Instant createTime;
}

特定のビジネスに応じてメッセージ処理結果を定義します。

3.2メッセージプロセッサ

抽象型

public interface MessageHandler {
    OutMessage handle(Message message, Map<String,Object> context);
}

これはすべてのメッセージプロセッサの抽象型であり、カスタムプロセッサで実装する必要があります。メッセージロギングプロセッサを実装するだけです。

@Component
public class LogMessageHandler implements MessageHandler {
    @Override
    public OutMessage handle(Message message, Map<String, Object> context) {
        System.out.println(message.toString());
        // define your return value
        return null;
    }
}

3.2ルーティング関連

メッセージインターセプター

public interface MessageInterceptor {
    OutMessage handle(Message message, Map<String,Object> context);
}

インターセプターは、メッセージの処理を強化できます。このインターフェースを自分で実装します。

メッセージマッチャー

public interface MessageRouterMatcher {
    boolean match(Message message);
}

マッチャーはメッセージをフィルタリングして、メッセージのルールマッチングを実現できます。

ルーター

public class MessageRouter {

    @Getter
    private final List<MessageRouterRule> rules = new ArrayList<>();

    public MessageRouterRule rule(){
        return new MessageRouterRule(this);
    }

    private OutMessage route(Message message,Map<String,Object> context){
        final List<MessageRouterRule> matchRules = new ArrayList<>();
        final Iterator<MessageRouterRule> iterator = this.rules.iterator();
        while (iterator.hasNext()){
            final MessageRouterRule rule = iterator.next();
            if (rule.test(message)){
                matchRules.add(rule);
            }
        }
        if(matchRules.size() == 0){
            return null;
        }else{
            final Iterator<MessageRouterRule> matchIterator = matchRules.iterator();
            while (matchIterator.hasNext()){
                final MessageRouterRule rule = matchIterator.next();
                //think think multi  OutMessage
                return rule.service(message, context);
            }
        }
        return null;
    }

    public OutMessage route(Message message){
        return this.route(message,new HashMap<>(2));
    }
}

メッセージルーティングルール

public class MessageRouterRule {

    //是否异步处理消息
    private boolean async;
    private String event;
    private String msgType;
    private String content;
    private String fromUser;
    private String toUser;

    /**
     * 路由器
     */
    private MessageRouter router;
    /**
     * 匹配器
     */
    private MessageRouterMatcher matcher;
    /**
     * 处理器
     */
    private List<MessageHandler> handlers = new ArrayList<>();
    /**
     * 拦截器 
     */
    private List<MessageInterceptor> interceptors = new ArrayList<>();


    public MessageRouterRule async(boolean async){
        this.async = async;
        return this;
    }

    public MessageRouterRule msgType(String msgType){
        this.msgType = msgType;
        return this;
    }

    public MessageRouterRule event(String event){
        this.event = event;
        return this;
    }

    public MessageRouterRule content(String content){
        this.content= content;
        return this;
    }

    public MessageRouterRule fromUser(String fromUser){
        this.fromUser= fromUser;
        return this;
    }

    public MessageRouterRule toUser(String toUser){
        this.toUser= toUser;
        return this;
    }

    public MessageRouterRule handler(MessageHandler handler,MessageHandler... otherHandlers){
        this.handlers.add(handler);
        if(otherHandlers != null && otherHandlers.length>0){
            Collections.addAll(this.handlers,otherHandlers);
        }
        return this;
    }

    public MessageRouterRule handle(MessageHandler handler){
        return this.handler(handler,(MessageHandler[]) null);
    }

    public MessageRouter end(){
        this.router.getRules().add(this);
        return this.router;
    }

    protected boolean test(Message message){
        //here can use matcher
        return (this.fromUser == null || this.fromUser.equals(message.getFromUser())) && (this.msgType == null || this.msgType.toLowerCase().equals(message.getMsgType() == null ? null : message.getMsgType().toLowerCase())) && (this.event == null || this.event.toLowerCase().equals(message.getEvent() == null ? null : message.getEvent().toLowerCase())) && (this.content == null || this.content.equals(message.getContent() == null ? null : message.getContent().trim())) && (this.matcher == null || this.matcher.match(message));
    }

    public MessageRouterRule(MessageRouter router){
        this.router = router;
    }

    protected OutMessage service(Message message, Map<String,Object> context){
        OutMessage outMessage = null;
        final Iterator<MessageHandler> iterator = handlers.iterator();
        while (iterator.hasNext()){
            final MessageHandler handler = iterator.next();
            if(null != handler){
                outMessage = handler.handle(message,context);
            }
        }
        return outMessage;
    }
}

メッセージルーターには、さまざまなメッセージルーティングルールが含まれています。

メッセージルーティングルールは、インターセプターを介したすべてのメッセージの処理を強化し、マッチャーを介してメッセージをフィルタリングおよび照合します。複数のプロセッサを同時に統合して、メッセージの最終処理を完了します。

4、テスト

このテストではspringフレームワークを使用します。

最初に構成クラスを実装しますbean

@Configuration
public class MessageRouterConfiguration {

    final LogMessageHandler logMessageHandler;

    public MessageRouterConfiguration(LogMessageHandler logMessageHandler) {
        this.logMessageHandler = logMessageHandler;
    }

    @Bean
    @ConditionalOnMissingBean(value = MessageRouter.class)
    public MessageRouter newRouter(){
        final MessageRouter messageRouter = new MessageRouter();
        //log print router rule
        messageRouter.rule().async(false).event("event").handle(logMessageHandler).end();
        //... add more
        return messageRouter;
    }
}

メッセージルーティングコール

アプリケーションの入り口でメッセージをルーティングし、結果を取得します

final OutMessage outMessage = router.route(message);

最終的に、ログ情報は端末に印刷されます。

五数要約

このモデルは単純なメッセージルーティングモデルのみを実装しており、次のような改善すべき領域がまだたくさんあります。

  • 複数のメッセージプロセッサの実行結果を処理する
  • メッセージを非同期的に処理する
  • メッセージは繰り返し消費される可能性があります
  • ..。

次の反復が最適化されるのを待ちます!コミュニケーションのためのメッセージを残すことを歓迎します。

おすすめ

転載: blog.csdn.net/qq_38082146/article/details/115091385