最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Spring的RPC通訊模型的使用與比較

 更新時(shí)間:2018年09月19日 10:02:31   作者:JMCui  
這篇文章主要介紹了基于Spring的RPC通訊模型的使用與比較,詳細(xì)的介紹了RMI、Caucho的Hessian和Burlap以及Spring自帶的HTTP invoker,感興趣的可以了解一下

一、概念和原理

RPC(remote procedure call),遠(yuǎn)程過程調(diào)用,是客戶端應(yīng)用和服務(wù)端之間的會(huì)話。在客戶端,它所需要的一些功能并不在該應(yīng)用的實(shí)現(xiàn)范圍之內(nèi),所以應(yīng)用要向提供這些功能的其他系統(tǒng)尋求幫助。而遠(yuǎn)程應(yīng)用通過遠(yuǎn)程服務(wù)暴露這些功能。RPC 是同步操作,會(huì)阻塞調(diào)用代碼的執(zhí)行,直到被調(diào)用的過程執(zhí)行完畢。

Spring支持多種不同的RPC模型,包括RMI、Caucho的Hessian和Burlap以及Spring自帶的HTTP invoker:

客戶端:

在所有的模型中,服務(wù)都是作為 Spring 所管理的 bean 配置到我們的應(yīng)用中。這是通過一個(gè)代理工廠 bean 實(shí)現(xiàn)的,這個(gè)bean能夠把遠(yuǎn)程服務(wù)像本地對象一樣裝配到其他bean的屬性中。

客戶端向代理發(fā)起調(diào)用,就像代理提供了這些服務(wù)一樣。代理代表客戶端和遠(yuǎn)程服務(wù)進(jìn)行通信,由它負(fù)責(zé)處理連接的細(xì)節(jié)并向遠(yuǎn)程服務(wù)發(fā)起調(diào)用。

服務(wù)端:

Spring 使用遠(yuǎn)程導(dǎo)出器(remote exporter)將bean方法發(fā)布為遠(yuǎn)程服務(wù)。

二、RMI

RMI 最初在JDK 1.1被引入到Java平臺(tái)中,它為Java開發(fā)者提供了一種強(qiáng)大的方法來實(shí)現(xiàn)Java程序間的交互。

Spring 提供了簡單的方式來發(fā)布RMI服務(wù),在服務(wù)端,RmiServiceExporter 可以把任何 Spring 管理的bean發(fā)布為RMI服務(wù) ,如圖所示,RmiServiceExporter 把bean包裝在一個(gè)適配器類中,然后適配器類被綁定到RMI注冊表中,并且代理到服務(wù)類的請求。

/**
   * 服務(wù)端:
   * <p>
   * 1、默認(rèn)情況下,RmiServiceExporter 會(huì)嘗試綁定到本地機(jī)器1099端口上的RMI注冊表。
   * 2、如果在這個(gè)端口沒有發(fā)現(xiàn)RMI注冊表,RmiServiceExporter 將會(huì)啟動(dòng)一個(gè)注冊表。
   * 3、可重寫注冊表的路徑和端口,這個(gè)是個(gè)大坑,當(dāng)你設(shè)置了registryHost屬性的時(shí)候,源碼中就不創(chuàng)建Registry,而是直接去獲取,可是我們自己也沒有創(chuàng)建,所以就會(huì)報(bào)連接不上。
   *
   * @param userService
   * @return
   */
  @Bean(name = "rmiServiceExporter")
  public RmiExporter rmiServiceExporter(UserService userService, Environment environment) {
    String registryHost = environment.getProperty("registryHost");
    int registryPort = environment.getProperty("registryPort", Integer.class);
    RmiExporter rmiExporter = new RmiExporter();
    rmiExporter.setService(userService); //要把該bean(即rmiServiceImpl)發(fā)布為一個(gè)RMI服務(wù)
    rmiExporter.setServiceName("RmiService"); //命名RMI 服務(wù)
    rmiExporter.setServiceInterface(UserService.class); //指定服務(wù)所實(shí)現(xiàn)的接口
    rmiExporter.setRegistryHost(registryHost);
    rmiExporter.setRegistryPort(registryPort);
    return rmiExporter;
  }
/**
 * Created by XiuYin.Cui on 2018/5/14.
 * 
 * 解決設(shè)置 registryHost 后,報(bào)連接拒絕的問題。
 */
public class RmiExporter extends RmiServiceExporter {

  @Override
  protected Registry getRegistry(String registryHost, int registryPort, RMIClientSocketFactory clientSocketFactory,
                  RMIServerSocketFactory serverSocketFactory) throws RemoteException {


    if (registryHost != null) {
      try {
        if (logger.isInfoEnabled()) {
          logger.info("Looking for RMI registry at port '" + registryPort + "' of host [" + registryHost + "]");
        }
        //把spring源代碼中這里try起來,報(bào)異常就創(chuàng)建一個(gè)
        Registry reg = LocateRegistry.getRegistry(registryHost, registryPort, clientSocketFactory);
        testRegistry(reg);
        return reg;
      } catch (RemoteException ex) {
        LocateRegistry.createRegistry(registryPort);
        Registry reg = LocateRegistry.getRegistry(registryHost, registryPort, clientSocketFactory);
        testRegistry(reg);
        return reg;
      }
    } else {
      return getRegistry(registryPort, clientSocketFactory, serverSocketFactory);
    }
  }
}

接下來,來看看客戶端是怎么使用這些遠(yuǎn)程服務(wù)的吧!Spring的RmiProxyFactoryBean是一個(gè)工廠bean,該bean可以為RMI服務(wù)創(chuàng)建代理。該代理代表客戶端來負(fù)責(zé)與遠(yuǎn)程的RMI服務(wù)進(jìn)行通信??蛻舳送ㄟ^服務(wù)的接口與代理進(jìn)行交互,就如同遠(yuǎn)程服務(wù)就是一個(gè)本地的POJO。

@Bean(name = "rmiUserServiceClient")
  public RmiProxyFactoryBean RmiUserServiceClient(){
    RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
    rmiProxyFactoryBean.setServiceUrl("rmi://127.0.0.1:9999/RmiService");
    rmiProxyFactoryBean.setServiceInterface(UserService.class);
    rmiProxyFactoryBean.setLookupStubOnStartup(false);//不在容器啟動(dòng)后創(chuàng)建與Server端的連接
    rmiProxyFactoryBean.setRefreshStubOnConnectFailure(true);//連接出錯(cuò)的時(shí)候自動(dòng)重連
    rmiProxyFactoryBean.afterPropertiesSet();
    return rmiProxyFactoryBean;
  }
 @Resource(name="rmiUserServiceClient")
  private UserService userService;

RMI 的缺陷:

1、RMI很難穿越防火墻,這是因?yàn)镽MI使用任意端口來交互——這是防火墻通常所不允許的。
2、RMI是基于Java的。這意味著客戶端和服務(wù)端必須都是用java開發(fā)。因?yàn)镽MI使用了Java的序列化機(jī)制,所以通過網(wǎng)絡(luò)傳輸?shù)膶ο箢愋捅仨氁WC在調(diào)用兩端的Java運(yùn)行時(shí)中是完全相同的版本。

tips:最近發(fā)現(xiàn)Dubbo 底層也是用 RMI 實(shí)現(xiàn)的,它把 zookeeper 當(dāng)作注冊表。

三、Hessian 和 Burlap

hessian 和 Burlap 是 Caucho Technology 的兩種基于HTTP的輕量級遠(yuǎn)程服務(wù)解決方案。借助于盡可能簡單的API和通信協(xié)議,它們都致力于簡化Web服務(wù)。

hessian,像RMI一樣,使用二進(jìn)制消息進(jìn)行客戶端和服務(wù)端的交互。但是它與RMI不同的是,它的二進(jìn)制消息可以移植到其他非Java的語言中。由于它是基于二進(jìn)制的,所以它在帶寬上更具優(yōu)勢。

Burlap 是一種基于XML的遠(yuǎn)程調(diào)用技術(shù),這使得它可以自然而然的移植到任何能夠解析XML的語言上。正因?yàn)樗赬ML,所以相比起Hessian的二進(jìn)制格式而言,Burlap可讀性更強(qiáng)。但是和其他基于XML的遠(yuǎn)程技術(shù)(例如SOAP或XML-RPC)不同,Burlap的消息結(jié)構(gòu)盡可能的簡單。

下面我們會(huì)介紹 hessian 的使用。Spring 不推薦使用Burlap,BurlapServiceExporter 在4.0后被廢棄,不再提供支持。5.0 后直接從開發(fā)包丟棄了。

服務(wù)端,類似于 RmiServiceExporter ,hessian 也有一個(gè)HessianServiceExporter 將 Spring 管理的 bean 發(fā)布為 Hessian 服務(wù),不同于RMI的是,HessianServiceExporter是一個(gè)Spring MVC控制器,它接收Hessian請求(HTTP協(xié)議的請求),并將這些請求轉(zhuǎn)換成對被導(dǎo)出POJO的方法調(diào)用。既然是HTTP請求,那我們就必須配置Spring 的DispatcherServlet ,并配置HandlerMapping,將相應(yīng)的URL映射給HessianServiceExporter。

/**
   * hessian沒有注冊表,不需要設(shè)置 serviceName
   */
  @Bean(name = "hessianServiceExporter")
  public HessianServiceExporter hessianServiceExporter(UserService userService) {
    HessianServiceExporter hessianServiceExporter = new HessianServiceExporter();
    hessianServiceExporter.setService(userService);
    hessianServiceExporter.setServiceInterface(UserService.class);
    return hessianServiceExporter;
  }
  /**
   * 需要配置一個(gè)URL映射來確保DispatcherServlet把請求轉(zhuǎn)給HessianServiceExporter
   */
  @Bean(name = "handlerMapping")
  public HandlerMapping handlerMapping() {
    SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
    Properties mappings = new Properties();
    mappings.setProperty("/user.service", "hessianServiceExporter");
    handlerMapping.setMappings(mappings);
    return handlerMapping;
  }

客戶端,類似于RmiProxyFactoryBean ,Hessian 也有一個(gè)代理工廠Bean——HessianProxyFactoryBean,來創(chuàng)建代理與遠(yuǎn)程服務(wù)進(jìn)行通信:

@Bean(name = "hessianUserServiceClient")
  public HessianProxyFactoryBean hessianUserServiceClient(){
    HessianProxyFactoryBean proxy = new HessianProxyFactoryBean();
    proxy.setServiceUrl("http://127.0.0.1:8080/user.service");
    proxy.setServiceInterface(UserService.class);
    return proxy;
  }
  @Resource(name="hessianUserServiceClient")
  private UserService userService; 

Hessian 的缺陷:

hessian 和 Burlap 都是基于HTTP的,它們都解決了RMI所頭疼的防火墻滲透問題。但是當(dāng)傳遞過來的RPC消息中包含序列化對象時(shí),RMI就完勝 Hessian 和 Burlap 了。因?yàn)?Hessian 和 Burlap 都采用了私有的序列化機(jī)制,而RMI使用的是Java本身的序列化機(jī)制。

四、HttpInvoker

RMI 和 Hessian 各有自己的缺陷,一方面,RMI使用Java標(biāo)準(zhǔn)的對象序列化機(jī)制,但是很難穿透防火墻。另一方面,Hessian和Burlap能很好地穿透防火墻,但是使用私有的對象序列化機(jī)制。就這樣,Spring的HTTP invoker應(yīng)運(yùn)而生了。HTTP invoker是一個(gè)新的遠(yuǎn)程調(diào)用模型,作為Spring框架的一部分,能夠執(zhí)行基于HTTP的遠(yuǎn)程調(diào)用,并使用Java的序列化機(jī)制。

HttpInvoker 的使用和 Hessian 很類似,HttpInvokerServiceExporter 也是一個(gè)Spring MVC 控制器,也是通過DispatcherServlet 將請求分發(fā)給它...

/*Http Invoker*/
  @Bean(name = "httpInvokerServiceExporter")
  public HttpInvokerServiceExporter httpInvokerServiceExporter(UserService userService){
    HttpInvokerServiceExporter httpInvokerServiceExporter = new HttpInvokerServiceExporter();
    httpInvokerServiceExporter.setService(userService);
    httpInvokerServiceExporter.setServiceInterface(UserService.class);
    return httpInvokerServiceExporter;
  }
  /**
   * 需要配置一個(gè)URL映射來確保DispatcherServlet把請求轉(zhuǎn)給HessianServiceExporter
   */
  @Bean(name = "handlerMapping")
  public HandlerMapping handlerMapping() {
    SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
    Properties mappings = new Properties();
    mappings.setProperty("/user.service", "hessianServiceExporter");
    mappings.setProperty("/userInvoker.service", "httpInvokerServiceExporter");
    handlerMapping.setMappings(mappings);
    return handlerMapping;
  }

客戶端,像 RmiProxyFactoryBean 和 HessianProxyFactoryBean 一樣,HttpInvoker 也提供了一個(gè)代理工廠Bean——HttpInvokerProxyFactoryBean,用于創(chuàng)建HttpInvoker代理來與遠(yuǎn)程服務(wù)通信:

@Bean(name = "httpInvokerUserServiceClient")
  public HttpInvokerProxyFactoryBean httpInvokerUserServiceClient(){
    HttpInvokerProxyFactoryBean proxy = new HttpInvokerProxyFactoryBean();
    proxy.setServiceUrl("http://127.0.0.1:8080//userInvoker.service");
    proxy.setServiceInterface(UserService.class);
    return proxy;
  }

參考資料:《Spring 實(shí)戰(zhàn)第四版》

演示源代碼鏈接:https://github.com/JMCuixy/SpringForRpc

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解基于java的Socket聊天程序——服務(wù)端(附demo)

    詳解基于java的Socket聊天程序——服務(wù)端(附demo)

    這篇文章主要介紹了詳解基于java的Socket聊天程序——服務(wù)端(附demo),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2016-12-12
  • java實(shí)現(xiàn)24點(diǎn)游戲

    java實(shí)現(xiàn)24點(diǎn)游戲

    每次取出4張牌,使用加減乘除,第一個(gè)能得出24者為贏,這篇文章主要就為大家詳細(xì)介紹了java實(shí)現(xiàn)24點(diǎn)游戲,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-01-01
  • 淺談JAVA工作流的優(yōu)雅實(shí)現(xiàn)方式

    淺談JAVA工作流的優(yōu)雅實(shí)現(xiàn)方式

    這篇文章主要介紹了淺談JAVA工作流的優(yōu)雅實(shí)現(xiàn)方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-11-11
  • Java @Deprecated注解的作用及傳遞性

    Java @Deprecated注解的作用及傳遞性

    用 @Deprecated注解的程序元素,不鼓勵(lì)程序員使用這樣的元素,通常是因?yàn)樗芪kU(xiǎn)或存在更好的選擇,本文給大家介紹java @deprecated注解的作用及傳遞性,對本文感興趣的朋友一起學(xué)習(xí)吧
    2015-12-12
  • 基于Java代碼實(shí)現(xiàn)數(shù)字在數(shù)組中出現(xiàn)次數(shù)超過一半

    基于Java代碼實(shí)現(xiàn)數(shù)字在數(shù)組中出現(xiàn)次數(shù)超過一半

    這篇文章主要介紹了基于Java代碼實(shí)現(xiàn)數(shù)字在數(shù)組中出現(xiàn)次數(shù)超過一半的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • spring中@value注解需要注意的問題

    spring中@value注解需要注意的問題

    本篇文章主要介紹了spring中@value注解需要注意的問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03
  • Java 利用枚舉實(shí)現(xiàn)接口進(jìn)行統(tǒng)一管理

    Java 利用枚舉實(shí)現(xiàn)接口進(jìn)行統(tǒng)一管理

    這篇文章主要介紹了Java 利用枚舉實(shí)現(xiàn)接口進(jìn)行統(tǒng)一管理,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • java實(shí)現(xiàn)圖書館管理系統(tǒng)

    java實(shí)現(xiàn)圖書館管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)圖書館管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-10-10
  • Java后臺(tái)返回和處理JSon數(shù)據(jù)的方法步驟

    Java后臺(tái)返回和處理JSon數(shù)據(jù)的方法步驟

    這篇文章主要介紹了Java后臺(tái)返回和處理JSon數(shù)據(jù)的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • win7下安裝 JDK 基本流程

    win7下安裝 JDK 基本流程

    這篇文章主要介紹了win7下安裝 JDK 基本流程,需要的朋友可以參考下
    2014-05-05

最新評論

三都| 尼勒克县| 玛纳斯县| 晋城| 壶关县| 黔江区| 富平县| 桦川县| 乐东| 白城市| 阿勒泰市| 北票市| 嵊州市| 淮南市| 新野县| 呼伦贝尔市| 游戏| 台南市| 沙湾县| 城口县| 兴义市| 怀来县| 盐源县| 丹棱县| 绥芬河市| 新竹市| 苏尼特左旗| 东乌珠穆沁旗| 文化| 漳平市| 囊谦县| 哈尔滨市| 自治县| 渭南市| 台中县| 中宁县| 丹东市| 康保县| 贡觉县| 高安市| 陆川县|