1. HTTP接口的意義前端
二進制接口使用的是java/hessian序列化協議,不能很好的與其餘語言通訊,雖然hessian也是一種跨語言的通用協議,但不少語言沒有很好的實現該協議的產品。
因此爲了可以與其餘語言進行服務通訊,咱們實現了http + json的協議實現,利用json原生的跨語言的特性。java
2. 原理簡圖json
描述:經過Netty暴露http服務端口,接收到http請求,經過HttpDecoder將其解析爲HttpRequest,經過JSONDecoder提取service請求信息,生成Request請求對象,從而adapt到binary協議實現,交由request processor處理,返回Response結果,最終經過JSONEncoder編碼爲JSON格式數據,再經過HttpEncoder生成HttpResponse返回給Http接口調用方。數組
3. 協議格式安全
假定:有服務暴露接口ExampleService,服務名稱:http://service.huifu.com/ExampleService/exampleService_1.0.0,定義了服務方法public String sayHello(String message),則HTTP訪問協議描述以下:框架
請求協議:eclipse
Name | Value | Description | |
---|---|---|---|
URL | http://{machine-ip}:{http-port}/rpc.json | HTTP服務的訪問地址,注意http端口號爲pegasus端口號+1000,即:pegasus配置爲8888,http端口就是9888 | |
Method | POST | 訪問方式,推薦使用POST方式 | |
Encoding | UTF-8 | HTTP請求編碼 | |
Params | _service | http://service.huifu.com/ExampleService/exampleService_1.0.0maven |
訪問的服務名稱 |
_method | sayHello測試 |
訪問的服務接口方法名稱 | |
_param | {"message" : "kitty"} | 傳遞到接口方法的參數值,使用json格式,形如:{"param1" : "value1", "param2" : {"f1" : 1, "f2" : "vvv"}},其中param1,param2爲方法的參數名稱,param1爲string類型,param2爲javabean類型,f1和f2爲該javabean的屬性名。ui 如:調用方法爲sayHello(String message),則對應json爲{"message":"kitty"}。若是調用方法爲:sayHello(RequestDTO userDTO),RequestDTO中有一個屬性爲name,則對應的json爲{"userDTO":{"name":"kitty"}}。 |
響應協議:
Name | Value | Description |
---|---|---|
格式 | {"type" : "xxx", "result" : "xxx", "error" : "xxx"} | HTTP服務接口的響應內容爲JSON格式 |
type | "service" | "service-exception" | "exception" | "service":業務處理正常返回 |
result | type = "service"時,服務方法的返回值,爲JSON格式 | 若方法返回值爲簡單類型: |
error | type = "service-exception" | "exception"時,返回的錯誤信息,爲JSON格式 |
形如{"type" : "com.huifu.xx.BizException", "message" : "order_no is not supported"} |
關於服務方法參數名
默認狀況下,pegasus經過asm讀取服務實現類的方法簽名信息,獲取方法的參數名,但因重構或其餘緣由,該方法的參數名有可能被修改,從而致使原有的http接口使用方沒法正常調用;
因此推薦在有可能提供http訪問的服務方法上經過@Param註解定義參數名,這樣就能夠防止參數名被修改的狀況,如void sayHello(@Param("message") String message),此時該方法就能夠安全地重構爲void sayHello(@Param("message") String msg),而不影響原有調用方;注意:在使用的過程當中發現,經過javassist獲取參數名,若是使用javac編譯器編譯的class文件(maven默認使用),可能會出現沒法讀取參數名或讀取錯誤; 咱們遇到的幾個問題case改用eclipse的ecj編譯器後均可以fix,但咱們沒法去測試覆蓋全部的代碼case,所以若方法涉及到http調用時,請使用@Param的方式顯式提供參數名; btw: maven使用ecj做爲編譯器的詳細配置以下 (1.0.2中已經使用asm替換javassist,該問題已FIXED)