• spring cloud bus原理总结


    1、spring cloud bus

      spring cloud是按照spring的配置对一系列微服务框架的集成,spring cloud bus是其中一个微服务框架,用于实现微服务之间的通信。
      spring cloud bus整合 java的事件处理机制和消息中间件消息的发送和接受,主要由发送端、接收端和事件组成。针对不同的业务需求,可以设置不同的事件,发送端发送事件,接收端接受相应的事件,并进行相应的处理。

    2、spring cloud bus实战

      网上关于spring cloud bus的demo相当多,此处就不赘述了。

    3、原理

      spring cloud bus整合了java的事件处理机制和消息中间件,所以下面就从这两个方面来说明spring cloud bus的原理。

    如图所示,作如下解释:

    (1)完整流程:发送端(endpoint)构造事件event,将其publish到context上下文中(spring cloud bus有一个父上下文,bootstrap),然后将事件发送到channel中(json串message),接收端从channel中获取到message,将message转为事件event(转换过程这一块没有深究),然后将event事件publish到context上下文中,最后接收端(Listener)收到event,调用服务进行处理。整个流程中,只有发送/接收端从context上下文中取事件和发送事件是需要我们在代码中明确写出来的,其它部分都由框架封装完成。

    (2)先大致描述了一下流程,关于封装的部分流程,我们基本上可以在BusAutoConfiguration.class中找到,下面的代码都是这个类中的代码

      @EventListener(classes = RemoteApplicationEvent.class)
        public void acceptLocal(RemoteApplicationEvent event) {
            if (this.serviceMatcher.isFromSelf(event)
                    && !(event instanceof AckRemoteApplicationEvent)) {
                this.cloudBusOutboundChannel.send(MessageBuilder.withPayload(event).build());
            }
        }

    这是封装了java事件处理机制,当收到RemoteApplicationEvent时,如果这个event是从这个服务发出的,而且不是ack事件,那么就会把这个事件发送到channel中。

      @StreamListener(SpringCloudBusClient.INPUT)
        public void acceptRemote(RemoteApplicationEvent event) {
            if (event instanceof AckRemoteApplicationEvent) {
                if (this.bus.getTrace().isEnabled() && !this.serviceMatcher.isFromSelf(event)
                        && this.applicationEventPublisher != null) {
                    this.applicationEventPublisher.publishEvent(event);
                }
                // If it's an ACK we are finished processing at this point
                return;
            }
            if (this.serviceMatcher.isForSelf(event)
                    && this.applicationEventPublisher != null) {
                if (!this.serviceMatcher.isFromSelf(event)) {
                    this.applicationEventPublisher.publishEvent(event);
                }
                if (this.bus.getAck().isEnabled()) {
                    AckRemoteApplicationEvent ack = new AckRemoteApplicationEvent(this,
                            this.serviceMatcher.getServiceId(),
                            this.bus.getAck().getDestinationService(),
                            event.getDestinationService(), event.getId(), event.getClass());
                    this.cloudBusOutboundChannel
                            .send(MessageBuilder.withPayload(ack).build());
                    this.applicationEventPublisher.publishEvent(ack);
                }
            }
            if (this.bus.getTrace().isEnabled() && this.applicationEventPublisher != null) {
                // We are set to register sent events so publish it for local consumption,
                // irrespective of the origin
                this.applicationEventPublisher.publishEvent(new SentApplicationEvent(this,
                        event.getOriginService(), event.getDestinationService(),
                        event.getId(), event.getClass()));
            }
        }

    @StreamListener这个标签有兴趣的可以去了解一下。这个方法就是从channel中取出事件进行处理的过程(message转事件部分需要自行了解,我没有深入研究),根据事件的类型、发送方和接收方来处理这个事件:如果是ack事件,发送到context上下文中;如果自己是接收端且不是发送端,就会将事件发送到context上下文。

    (3)消息中间件可以采用rabbitmq、kafka之类的

    (4)说两个比较有意思的问题

      1)自定义事件时,我们需要添加无参构造方法:目的在于,在message转事件时,会调用这个无参构造方法,具体情况可以去参考源码看看

      2)自定义事件时,事件的参数需要用final修饰,这个一直没有找到合理的解释,有兴趣可以去研究研究

  • 相关阅读:
    jdk环境变量配置
    智商太低,竟然算不出病狗神题了
    HDU 1284 钱币兑换问题 母函数、DP
    linux下实现监控进程网络带宽
    编程算法
    C語言 rand函数 进阶探讨与实现
    JDBCUtil
    iOS进阶路线以及进阶书籍
    Windows平台CUDA开发之前的准备工作
    数据库中substring的用法 CONVERT(varchar(12) , getdate(), 112 )
  • 原文地址:https://www.cnblogs.com/songxh-scse/p/7833963.html
Copyright © 2020-2023  润新知