1. 程式人生 > >RPC和HTTP

RPC和HTTP

在這裡插入圖片描述

1.1.認識RPC

RPC,即 Remote Procedure Call(遠端過程呼叫),是一個計算機通訊協議。 該協議允許運行於一臺計算機的程式呼叫另一臺計算機的子程式,而程式設計師無需額外地為這個互動作用程式設計。說得通俗一點就是:A計算機提供一個服務,B計算機可以像呼叫本地服務那樣呼叫A計算機的服務。

通過上面的概念,我們可以知道,實現RPC主要是做到兩點:

  • 實現遠端呼叫其他計算機的服務
    • 要實現遠端呼叫,肯定是通過網路傳輸資料。A程式提供服務,B程式通過網路將請求引數傳遞給A,A本地執行後得到結果,再將結果返回給B程式。這裡需要關注的有兩點:
      • 1)採用何種網路通訊協議?
        • 現在比較流行的RPC框架,都會採用TCP作為底層傳輸協議
      • 2)資料傳輸的格式怎樣?
        • 兩個程式進行通訊,必須約定好資料傳輸格式。就好比兩個人聊天,要用同一種語言,否則無法溝通。所以,我們必須定義好請求和響應的格式。另外,資料在網路中傳輸需要進行序列化,所以還需要約定統一的序列化的方式。
  • 像呼叫本地服務一樣呼叫遠端服務
    • 如果僅僅是遠端呼叫,還不算是RPC,因為RPC強調的是過程呼叫,呼叫的過程對使用者而言是應該是透明的,使用者不應該關心呼叫的細節,可以像呼叫本地服務一樣呼叫遠端服務。所以RPC一定要對呼叫的過程進行封裝

RPC呼叫流程圖:
在這裡插入圖片描述
想要了解詳細的RPC實現,給大家推薦一篇文章:自己動手實現RPC

1.2.認識Http

Http協議:超文字傳輸協議,是一種應用層協議。規定了網路傳輸的請求格式、響應格式、資源定位和操作的方式等。但是底層採用什麼網路傳輸協議,並沒有規定,不過現在都是採用TCP協議作為底層傳輸協議。說到這裡,大家可能覺得,Http與RPC的遠端呼叫非常像,都是按照某種規定好的資料格式進行網路通訊,有請求,有響應。沒錯,在這點來看,兩者非常相似,但是還是有一些細微差別。

  • RPC並沒有規定資料傳輸格式,這個格式可以任意指定,不同的RPC協議,資料格式不一定相同。
  • Http中還定義了資源定位的路徑,RPC中並不需要
  • 最重要的一點:RPC需要滿足像呼叫本地服務一樣呼叫遠端服務,也就是對呼叫過程在API層面進行封裝。Http協議沒有這樣的要求,因此請求、響應等細節需要我們自己去實現。
    • 優點:RPC方式更加透明,對使用者更方便。Http方式更靈活,沒有規定API和語言,跨語言、跨平臺
    • 缺點:RPC方式需要在API層面進行封裝,限制了開發的語言環境。

例如我們通過瀏覽器訪問網站,就是通過Http協議。只不過瀏覽器把請求封裝,發起請求以及接收響應,解析響應的事情都幫我們做了。如果是不通過瀏覽器,那麼這些事情都需要自己去完成。
在這裡插入圖片描述

1.3.如何選擇?

既然兩種方式都可以實現遠端呼叫,我們該如何選擇呢?

  • 速度來看,RPC要比http更快,雖然底層都是socket,但是http協議的資訊往往比較臃腫
  • 難度來看,RPC實現較為複雜,http相對比較簡單
  • 靈活性來看,http更勝一籌,因為它不關心實現細節,跨平臺、跨語言。

因此,兩者都有不同的使用場景:

  • 如果對效率要求更高,並且開發過程使用統一的技術棧,那麼用RPC還是不錯的。
  • 如果需要更加靈活,跨語言、跨平臺,顯然http更合適

那麼我們該怎麼選擇呢?

微服務,更加強調的是獨立、自治、靈活。而RPC方式的限制較多,因此微服務框架中,一般都會採用基於Http的Rest風格服務。

1.4.Spring的RestTemplate

Spring提供了一個RestTemplate模板工具類,對基於Http的客戶端進行了封裝,並且實現了物件與json的序列化和反序列化,非常方便。RestTemplate並沒有限定Http的客戶端型別,而是進行了抽象,目前常用的3種都有支援:

  • HttpClient

  • OkHttp

  • JDK原生的URLConnection(預設的)
    首先在專案中註冊一個RestTemplate物件,可以在啟動類位置註冊:

     @SpringBootApplication
      public class HttpDemoApplication {
      
      	public static void main(String[] args) {
      		SpringApplication.run(HttpDemoApplication.class, args);
      	}
      
      	@Bean
      	public RestTemplate restTemplate() {
              // 預設的RestTemplate,底層是走JDK的URLConnection方式。
      		return new RestTemplate();
      	}
      }
    

在測試類中直接@Autowired注入:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = HttpDemoApplication.class)
public class HttpDemoApplicationTests {

	@Autowired
	private RestTemplate restTemplate;

	@Test
	public void httpGet() {
		User user = this.restTemplate.getForObject("http://localhost/hello", User.class);
		System.out.println(user);
	}
}
  • 通過RestTemplate的getForObject()方法,傳遞url地址及實體類的位元組碼,RestTemplate會自動發起請求,接收響應,並且幫我們對響應結果進行反序列化。
    在這裡插入圖片描述

RPC和http之間的區別?

  • 速度來看,RPC要比http更快,雖然底層都是socket,但是http協議的資訊往往比較臃腫,傳輸的資料比較多,速度相對慢

  • 難度來看,RPC實現較為複雜,啟動需要消耗更多的記憶體和CPU資源,http相對比較簡單

  • 靈活性來看,http更勝一籌,因為它不關心實現細節,跨平臺、跨語言。http只需要提供restful風格的介面,

    RPC要求伺服器和客戶端都採用相同的框架