激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 基于Spring的RPC通訊模型的使用與比較

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

2021-06-01 11:25JMCui Java教程

這篇文章主要介紹了基于Spring的RPC通訊模型的使用與比較,詳細的介紹了RMI、Caucho的Hessian和Burlap以及Spring自帶的HTTP invoker,感興趣的可以了解一下

一、概念和原理

 

rpc(remote procedure call),遠程過程調用,是客戶端應用和服務端之間的會話。在客戶端,它所需要的一些功能并不在該應用的實現范圍之內,所以應用要向提供這些功能的其他系統尋求幫助。而遠程應用通過遠程服務暴露這些功能。rpc 是同步操作,會阻塞調用代碼的執行,直到被調用的過程執行完畢。

spring支持多種不同的rpc模型,包括rmi、caucho的hessian和burlap以及spring自帶的http invoker:

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

客戶端:

在所有的模型中,服務都是作為 spring 所管理的 bean 配置到我們的應用中。這是通過一個代理工廠 bean 實現的,這個bean能夠把遠程服務像本地對象一樣裝配到其他bean的屬性中。

客戶端向代理發起調用,就像代理提供了這些服務一樣。代理代表客戶端和遠程服務進行通信,由它負責處理連接的細節并向遠程服務發起調用。

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

服務端:

spring 使用遠程導出器(remote exporter)將bean方法發布為遠程服務。

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

二、rmi

 

rmi 最初在jdk 1.1被引入到java平臺中,它為java開發者提供了一種強大的方法來實現java程序間的交互。

spring 提供了簡單的方式來發布rmi服務,在服務端,rmiserviceexporter 可以把任何 spring 管理的bean發布為rmi服務 ,如圖所示,rmiserviceexporter 把bean包裝在一個適配器類中,然后適配器類被綁定到rmi注冊表中,并且代理到服務類的請求。

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
/**
   * 服務端:
   * <p>
   * 1、默認情況下,rmiserviceexporter 會嘗試綁定到本地機器1099端口上的rmi注冊表。
   * 2、如果在這個端口沒有發現rmi注冊表,rmiserviceexporter 將會啟動一個注冊表。
   * 3、可重寫注冊表的路徑和端口,這個是個大坑,當你設置了registryhost屬性的時候,源碼中就不創建registry,而是直接去獲取,可是我們自己也沒有創建,所以就會報連接不上。
   *
   * @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)發布為一個rmi服務
    rmiexporter.setservicename("rmiservice"); //命名rmi 服務
    rmiexporter.setserviceinterface(userservice.class); //指定服務所實現的接口
    rmiexporter.setregistryhost(registryhost);
    rmiexporter.setregistryport(registryport);
    return rmiexporter;
  }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 * created by xiuyin.cui on 2018/5/14.
 *
 * 解決設置 registryhost 后,報連接拒絕的問題。
 */
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起來,報異常就創建一個
        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);
    }
  }
}

接下來,來看看客戶端是怎么使用這些遠程服務的吧!spring的rmiproxyfactorybean是一個工廠bean,該bean可以為rmi服務創建代理。該代理代表客戶端來負責與遠程的rmi服務進行通信。客戶端通過服務的接口與代理進行交互,就如同遠程服務就是一個本地的pojo。

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

?
1
2
3
4
5
6
7
8
9
10
@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);//不在容器啟動后創建與server端的連接
    rmiproxyfactorybean.setrefreshstubonconnectfailure(true);//連接出錯的時候自動重連
    rmiproxyfactorybean.afterpropertiesset();
    return rmiproxyfactorybean;
  }
?
1
2
@resource(name="rmiuserserviceclient")
 private userservice userservice;

rmi 的缺陷:

1、rmi很難穿越防火墻,這是因為rmi使用任意端口來交互——這是防火墻通常所不允許的。
2、rmi是基于java的。這意味著客戶端和服務端必須都是用java開發。因為rmi使用了java的序列化機制,所以通過網絡傳輸的對象類型必須要保證在調用兩端的java運行時中是完全相同的版本。

tips:最近發現dubbo 底層也是用 rmi 實現的,它把 zookeeper 當作注冊表。

三、hessian 和 burlap

 

hessian 和 burlap 是 caucho technology 的兩種基于http的輕量級遠程服務解決方案。借助于盡可能簡單的api和通信協議,它們都致力于簡化web服務。

hessian,像rmi一樣,使用二進制消息進行客戶端和服務端的交互。但是它與rmi不同的是,它的二進制消息可以移植到其他非java的語言中。由于它是基于二進制的,所以它在帶寬上更具優勢。

burlap 是一種基于xml的遠程調用技術,這使得它可以自然而然的移植到任何能夠解析xml的語言上。正因為它基于xml,所以相比起hessian的二進制格式而言,burlap可讀性更強。但是和其他基于xml的遠程技術(例如soap或xml-rpc)不同,burlap的消息結構盡可能的簡單。

下面我們會介紹 hessian 的使用。spring 不推薦使用burlap,burlapserviceexporter 在4.0后被廢棄,不再提供支持。5.0 后直接從開發包丟棄了。

服務端,類似于 rmiserviceexporter ,hessian 也有一個hessianserviceexporter 將 spring 管理的 bean 發布為 hessian 服務,不同于rmi的是,hessianserviceexporter是一個spring mvc控制器,它接收hessian請求(http協議的請求),并將這些請求轉換成對被導出pojo的方法調用。既然是http請求,那我們就必須配置spring 的dispatcherservlet ,并配置handlermapping,將相應的url映射給hessianserviceexporter。

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
   * hessian沒有注冊表,不需要設置 servicename
   */
  @bean(name = "hessianserviceexporter")
  public hessianserviceexporter hessianserviceexporter(userservice userservice) {
    hessianserviceexporter hessianserviceexporter = new hessianserviceexporter();
    hessianserviceexporter.setservice(userservice);
    hessianserviceexporter.setserviceinterface(userservice.class);
    return hessianserviceexporter;
  }
  /**
   * 需要配置一個url映射來確保dispatcherservlet把請求轉給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 也有一個代理工廠bean——hessianproxyfactorybean,來創建代理與遠程服務進行通信:

?
1
2
3
4
5
6
7
@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;
  }
?
1
2
@resource(name="hessianuserserviceclient")
private userservice userservice;

hessian 的缺陷:

hessian 和 burlap 都是基于http的,它們都解決了rmi所頭疼的防火墻滲透問題。但是當傳遞過來的rpc消息中包含序列化對象時,rmi就完勝 hessian 和 burlap 了。因為 hessian 和 burlap 都采用了私有的序列化機制,而rmi使用的是java本身的序列化機制。

四、httpinvoker

 

rmi 和 hessian 各有自己的缺陷,一方面,rmi使用java標準的對象序列化機制,但是很難穿透防火墻。另一方面,hessian和burlap能很好地穿透防火墻,但是使用私有的對象序列化機制。就這樣,spring的http invoker應運而生了。http invoker是一個新的遠程調用模型,作為spring框架的一部分,能夠執行基于http的遠程調用,并使用java的序列化機制。

httpinvoker 的使用和 hessian 很類似,httpinvokerserviceexporter 也是一個spring mvc 控制器,也是通過dispatcherservlet 將請求分發給它...

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*http invoker*/
  @bean(name = "httpinvokerserviceexporter")
  public httpinvokerserviceexporter httpinvokerserviceexporter(userservice userservice){
    httpinvokerserviceexporter httpinvokerserviceexporter = new httpinvokerserviceexporter();
    httpinvokerserviceexporter.setservice(userservice);
    httpinvokerserviceexporter.setserviceinterface(userservice.class);
    return httpinvokerserviceexporter;
  }
  /**
   * 需要配置一個url映射來確保dispatcherservlet把請求轉給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 也提供了一個代理工廠bean——httpinvokerproxyfactorybean,用于創建httpinvoker代理來與遠程服務通信:

?
1
2
3
4
5
6
7
@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 實戰第四版》

演示源代碼鏈接:https://github.com/jmcuixy/springforrpc

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://www.cnblogs.com/jmcui/p/9044212.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 中国大陆高清aⅴ毛片 | 国产又粗又爽又深的免费视频 | 国产精选在线 | 快播av在线| 在线中文字幕观看 | 91短视频在线观看视频 | 国产69精品99久久久久久宅男 | 黄视频免费观看 | 日本在线播放一区二区 | 宅男噜噜噜66国产在线观看 | 国产69精品久久久久久 | 一本色道久久99精品综合蜜臀 | 国产精品亚洲yourport | 欧美wwwsss9999| 色成人在线 | 欧美另类视频在线 | 久久国产精品二国产精品中国洋人 | 激情视频免费看 | 一级爱爱 | 黄色片在线观看网站 | 精品亚洲在线 | 九一国产精品 | 中国成人在线视频 | 一级片在线免费 | a级毛片免费观看在线播放 日本aaa一级片 | 精品国产一区二区三区天美传媒 | 亚洲91网站 | 92看片淫黄大片欧美看国产片 | 一区二区三区四区免费看 | 999精品国产 | 午夜精品福利视频 | xnxx 日本免费 | 免费观看国产精品视频 | 亚洲精品aⅴ中文字幕乱码 欧美囗交 | 国产一级免费片 | asian裸体佳人pics | 亚洲一区在线观看视频 | 国产伦久视频免费观看视频 | 欧美自拍三区 | 国产精品九九久久一区hh | 一级毛片在线视频 |