spring 远程调用服务同步RPC和异步消息MQ


远程调用服务,同步RPC


01、远程过程调用(remote procedure call,RPC):
    RPC类似于调用一个本地对象的一个方法。
    是同步操作,会阻塞调用代码的执行,直到被调用的过程执行完毕。这是与消息队列MQ最大的区别。
    所以这种方式的远程服务,也叫做同步RPC。


02、编程模型一致的Spring支持:
     2.1、服务端,配置ServiceExporter,导出Spring bean为服务端点(Endpoint),暴露端点的访问路径(serviceName),配置导出服务接口(serviceInterface)
     2.2、客户端,配置服务端点访问路径,使用xxProxyFactoryBean,为远程服务创建代理对象,然后注入使用,配置代理服务接口


1、远程调用服务是独立服务:
    1.1、RMI提供基于 RMI注册表 的独立服务。需要占用端口。所以存在防火墙穿透问题。
    1.2、Hessian、Burlap、HttpInvoker、JAX-WS、REST依赖HTTP服务器,提供基于的远程调用服务。
        其中针对Hessian、Burlap、HttpInvoker的Spring支持,提供了编程模型一致的方案:
            ServiceExporter本质上是一个SpringMVC控制器。同时,为了定义这个springMVC控制器的requestMapping,也是为了暴露远程服务端点endpoint,需要通过SimpleUrlHandlerMapping 这个spring bean配置URL和控制器(bean ID)之间的映射

    1.3、目前同步RPC服务,倾向于REST + json的方案来解决。。其他的参考了解。



3、RMI导出服务时配置的serviceName类似于URI,作为特定RMI服务端点的访问标识
    RMI客户端通过serviceUrl属性配置服务端点endpoint,访问协议是rmi,然后是host+port,然后是serviceName


4、对象的序列化机制,支撑RPC的对象远程传输。类似于MQ中的消息转换器。
    RMI、HttpInvoker,使用的是Java的对象序列化机制。Hessian、Burlap使用的私有机制,所以复杂对象可能出现问题


5、SOA面向服务的架构核心理念:
    公共的核心模块应该设计成独立服务,以集群方式提供弹性扩展,通过消息总线通信(或者同步RPC)
     集群是指服务的集群,可以弹性扩展。分布式是指资源数据的分布式存储。(我理解的区别就是,一个是计算服务,一个是数据资源存储服务)


7、RMI、Hessian、HttpInvoker都是基于二进制消息
    Burlap、webservice都是基于XML文本消息
    Hessian、Burlap、webservice可以屏蔽两端的语言差异(后两个是因为基于XML),RMI是Java自己关于远程方法调用的实现,HttpInvoker需要spring的支持

8、 只要是基于字符集charset的可读性数据,都是文本数据(文件)。。其他都是二进制数据。

9、导出webservice端点:
    9.1、针对POJO,使用@WebServise声明端点(serviceName属性指定端点名称)和@WebMethod声明操作
    9.2、JAX-WS运行时(jdk1.6自带实现支持,1.8不清楚是否支持)支持将端点发布到指定地址时,可以将SpringBean导出为端点,并且可以使用SimpleJaxWsServiceExporter作为导出器。
         同时可以指定baseAddress属性,来设置端点的基本地址,配合serviceName,可以实现,将端点发布到指定地址。
    9.3、当JAX-WS运行时不支持将端点发布为到指定地址时,端点的生命周期将由运行时来管理,如果要使用Spring自动装配特性,则必须继承SpringBeanAutowiringSupport。并且不能使用SimpleJaxWsServiceExporter导出器。具体怎么发布端点,语焉不详。

10、客服端访问Webservice端点,基于编程模型一致性,基本跟其他远程技术一样。
     区别时,有三个属性需要去wsdl文档中查看获取:serviceName、portName、namespaceUri





spring异步消息


1、消息驱动POJO,MDP。说白了就是配置一个基于POJO的监听器。
    
1A、配置:
  • 基于XML配置一个监听器容器(注入连接工厂),然后在其中配置一系列监听器。。
  • 监听器,指定Spring bean(POJO)、其中的方法、监听的目的地,并结合消息转换器,从而通过事件监听机制来实现异步接收消息。


2、基于Spring提供的编程模型一致性。。对JMS配置的MDP和对AMQP的基本一样


3、所以,除非通过xxTemplate主动从目的地接收消息,其他异步形式接收消息,本质上都是通过监听器监听目的地来实现的。


4、另外,虽然在JMS中,目的地分为queue和topic,但其实本质上,都是queue队列(要不怎么就有MQ消息队列的概念了)。
  • 无非topic是主题-订阅模型,在topic中的消息,会通过副本形式发送给所有监听该目的地的监听器(类似于订阅),然后从队列移除。
  • 而点对点模型,仅仅会被监听该目的地中其中一个收到(类似于消费),并从队列移除。
  • 这种区别,仅仅是消息路由模式的区别。
 

5、AMQP,则是通过exchange+binding+routing key的方式,来实现,更加灵活的消息路由模式。
    

6、在分布式集群项目中,消息作为常用的通信通道 而存在。又称作消息总线

7、异步消息核心概念:
  • 消息代理message Broker
    •  基于内存的
    • 基于独立服务的
      • 支持JMS的ActiveMQ
      • 支持AMQP的RabbitMQ
  • 目的地Destination




WebSocket以及基于WebSocket的STOMP消息



1、STOMP之于WebSocket,类似于http之于TCP socket

2、STOMP是底层基于WebSocket的一种消息协议,相对http的优势是,全双工通信

03、JMS、AMQP等消息协议,是用于两个应用之间的通信。这两个应用只是发送端、接收端的关系,不是客户端、服务端的关系
    而对于STOMP消息,它是用于web浏览器-web服务器之间通信的应用场景。所以,存在js客户端、STOMP服务端的概念。

3、Spring配置STOMP:
    3.1、启用WebSocket消息代理(@EnableWebSocketMessageBroker注解)
    3.2、继承AbstractWebSocketMessageBrokerConfigurer
    3.3、注册StompEndpoint。。用于客户端通过WebSocket来连接MessageHandler(消息处理器)。
    3.4、启用代理中继,注册代理目的地前缀、注册应用目的地前缀
            如果不启用代理中继,可以使用Spring的简单代理基于内存来提供消息代理服务

04、客户端在订阅或发布消息到目的地路径前,要连接端点StompEndpoint。
是因为客户端需要先跟web服务器通信,才能进一步经过MessageHandler处理,转发到消息代理服务器(或者像@SubscribeMapping直接返回客户端)

05、在远程服务中,提供服务的可调用接口,叫做端点Endpoint


4、STOMP消息目的地,分为应用目的地和代理目的地:
    其中应用目的地,由AnnotationMethodMessageHandler,根据@MessageMapping和@SubscribeMapping注解的路径,路由到相应的处理器方法中。。发往这里的消息,也叫应用消息
    代理目的地,则是由SimpleBrokerMessageHandler转发到简单代理中的目的地,或者如果启用了消息中继,则由StompBrokerRelayMessageHandler转发到第三方消息代理的目的地。发往这里的消息,也叫代理消息。



8、因为STOMP是消息协议,所以本质上存在几种概念:发送端、接受端、消息代理服务(消息总线)
    其中,任何一方发送和接收消息,都是与消息代理目的地之间的通信。不会存在,发送端和接收端的直接联系。
    然后,可以通过模版类(XXTemplate)主动发送、接收消息。。
    也可以通过监听(订阅)目的地的方式,被动接收消息(消息驱动POJO)


9、应用目的地,可以处理消息,也可以处理订阅:意思就是
     9.1、处理消息,就是@MessageMapping方法处理客户端通过stomp连接调用send之后所产生的消息。
     9.2、处理订阅,就是@SubscribeMapping方法处理客户端通过stomp连接调用subscribe 订阅应用目的地之后产生的消息,叫做订阅消息。
            客户端调用subscribe,首次都会发送一个订阅消息。但是发往应用目的地的订阅消息,有可能并没有经过消息代理,而是直接返回客户端。这时,这种订阅,就是一次性的请求-回应模式。因为订阅,要起到长期监听作用,必须由消息代理来支持。首次订阅消息,会起到一种注册观察者的作用。(这是我理解的,不知道对不对)
 
  

11、在STOMP消息模型中:
    11.1、js客户端:
        拿到SocketJS实例(连接StompEndpoint),拿到Stomp实例,连接(connect),在连接成功的回调方法中
            客户端发送消息(异步的吧?):调用send,传入目的地、header map、负载
            客户端接收消息(异步订阅):调用subscribe,传入目的地、回调函数

    11.2、web服务端:
        接收消息:接收的消息都是发往应用目的地的消息
            @MessageMapping接收应用消息
            @SubscribeMapping接收订阅消息:接收订阅应用目的地的消息
                @SubscribeMapping的特殊之处在于,以异步消息的形式实现类似于http请求-回应模型。
                当不存在@SendTo注解时,处理器返回后的消息,将直接发送给客户端(消息所带的destination就是原来的目的地),此时,消息不再经过消息代理。除非添加@SendTo注解,消息才会发布到消息代理。        
        
        发送消息:
            处理器方法的返回值
                @MessageMapping返回值和带@SendTo注解的@SubscribeMapping返回值,都将作为消息发布到消息代理。客户端通过订阅代理目的地,来接收消息。
                
                注意:  返回值发出的消息,还会经过MessageHandler进行处理,转发到消息代理目的地上   
            使用模版类,主动向目的地发送消息
                通过模版类( SimpMessagingTemplate,配置STOMP之后,Spring上下文就会有这个bean)、消息转换器,主动发送消息到目的地


12、结合Spring Security,实现为目标用户发送消息:
    跟用户绑定的消息,将使用UserDestinationMessageHandler来处理,叫做用户消息:
        12.1、客户端订阅/user前缀的目的地产生的订阅消息:
            如果客户端订阅了'/user/topic/greetings',服务端UserDestinationMessageHandler会将其转发到类似"/topic/greetings-usererbgz2rq"这样格式的目的地中,其中"usererbgz2rq"中,user是关键字,erbgz2rq是sessionid。这样客户端就会只订阅发布到当前用户当前会话的消息。
        12.2、处理器方法使用@SendToUser注解产生的返回值消息:
            服务端处理器方法@SendToUser('/topic/greetings')将发布消息到'/user/loginname/topic/greetings',其中loginname是结合Spring Security获得的当前登录用户帐号。。这时候,如果一个帐号打开了多个浏览器窗口,也就是打开了多个websocket session通道,UserDestinationMessageHandler转发时默认会把消息推送到同一个帐号所有session的用户目的地中,但可以将@SendToUser的属性broadcast = false,使得消息只推送到当前session(即发送订阅消息的那个session)
        12.3、通过模版类SimpMessagingTemplate,调用convertAndSendToUser('username', '/topic/greetings', XX),效果跟@SendToUser一样。区别是,可以在应用任意位置发送消息。
        

012、只要消息的目的地不是代理目的地,就会被相应的MessageHandler处理并转发,例如应用目的地、/user前缀目的地等。直到消息转发到代理目的地或者转发回客户端(@SubscribeMapping)


13、MessageHandler可接收到的消息:
    发往应用目的地的消息,由AnnotationMethodMessageHandler处理:
        应用消息@MessageMapping
        订阅消息@SubscribeMapping
    用户消息,由UserDestinationMessageHandler处理
    发往代理目的地的订阅消息,由SimpleBrokerMessageHandler或者StompBrokerRelayMessageHandler处理。
    

14、捕获消息处理器方法抛出的异常:
    @MessageExceptionHandler,基于spring的编程模型一致性,类似于SpringMVC中的@ExceptionHandler。。。同时借助@SendTo注解,可以发布一个回应消息
    





        
    
    




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值