Una implementación escalable de enrutamiento de mensajes

I. Introducción

Recientemente, al implementar los subprogramas de WeChat, es necesario procesar diferentes mensajes enviados desde el servidor de WeChat.Hay muchos tipos de mensajes, incluidos los mensajes de suscripción, mensajes gráficos, etc. Después de aprender de algunos patrones de diseño de grandes dioses, se implementa un modelo de enrutamiento de mensajes simple, que puede cumplir con múltiples tipos de mensajes, concordancia de enrutamiento múltiple y procesamiento de mensajes múltiples.

Dos, el modelo

image.png

  • El mensaje en sí tiene algunas cantidades características, que se pueden utilizar como base para hacer coincidir las reglas de enrutamiento de mensajes.

  • Un enrutador de mensajes contiene varias reglas de enrutamiento de mensajes.

  • Una regla de enrutamiento de mensajes incluye interceptores, comparadores y múltiples procesadores.

Tres, el código

3.1 Definición de mensaje

Código fuente: https://segmentfault.com/a/1190000039689926

Mensaje para ser consumido

@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
}

Información para el consumidor sea objeto contiene una serie de Traitcampos, incluyendo event, msgType, content. Estos campos se pueden utilizar no solo como base para hacer coincidir las reglas de enrutamiento, sino también como condiciones para procesar mensajes específicos. Puede ampliarse de acuerdo con diferentes tipos de negocios.

Resultado del procesamiento de mensajes

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

Defina el resultado del procesamiento de mensajes de acuerdo con su negocio específico.

3.2 Procesador de mensajes

Tipo abstracto

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

Este es un tipo abstracto de todos los procesadores de mensajes y los procesadores personalizados deben implementarlo. Simplemente implemente un procesador de registro de mensajes.

@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 Relacionado con el enrutamiento

Interceptor de mensajes

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

Los interceptores pueden mejorar el procesamiento de mensajes. Implemente esta interfaz usted mismo.

Coincidencia de mensajes

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

El comparador puede filtrar el mensaje para darse cuenta de la coincidencia de reglas del mensaje.

enrutador

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));
    }
}

Reglas de enrutamiento de mensajes

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;
    }
}

El enrutador de mensajes contiene una variedad de reglas de enrutamiento de mensajes.

Las reglas de enrutamiento de mensajes mejoran el procesamiento de todos los mensajes a través de interceptores y filtran y combinan mensajes a través de comparadores. Integre varios procesadores al mismo tiempo para completar el procesamiento final del mensaje.

Cuatro, prueba

Esta prueba utiliza un springmarco.

Primero implemente una clase de configuraciónbean

@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;
    }
}

Llamada de enrutamiento de mensajes

Enruta mensajes en la entrada de la aplicación y obtén el resultado

final OutMessage outMessage = router.route(message);

Finalmente, la información del registro se imprimirá en el terminal.

Cinco, resumen

Este modelo solo implementa un modelo de enrutamiento de mensajes simple, y todavía hay muchas áreas por mejorar, como

  • Manejar los resultados de ejecución de múltiples procesadores de mensajes
  • Procesar mensajes de forma asincrónica
  • Los mensajes pueden consumirse repetidamente
  • ...

¡Espere a que la próxima iteración se optimice! Bienvenido a dejar un mensaje para comunicarse.

Supongo que te gusta

Origin blog.csdn.net/qq_38082146/article/details/115091385
Recomendado
Clasificación