gRPC-web現狀及測試
本文主要介紹了gRPC-web現狀及測試的簡介、好不好用等相關內容。
gRPC是什麼?
gRPC是谷歌開源的一款不那麼快的基於原型緩衝區的RPC框架。
既然不那麼快,為什麼還要提它呢?相較於節儉,gRPC會慢一點,但是,本文的著眼點並不在於RPC吞吐量的極限值,也不是框架的通訊時間減少幾十幾千納秒,本文要介紹的是除GraphQL外,JSON RPC最佳化的另一個取向--gRPCweb。
眾所周知,GraphQL著眼的最佳化點在於透過移交一部分查詢的邏輯到客戶端,從而減少了資料的交換量,而RPC則著眼於使用可壓縮的二進位制/文字協議,減少JSON文字傳輸帶來的不必要的協議損失。本文著眼於此,對比gRPCweb當前的進展,對易用性,便捷性,成本方面進行了評價,結論雖然有些武斷,但是仍然反映了當前gRPCweb仍然有待進一步發展的事實。
1gRPC web能給我們帶來什麼?
1.傳輸資料量減少,傳輸延遲降低
HTTP / 2天生具有頭壓縮等特性,解決了大量頻繁的RPC互動通訊帶來的頭部重複傳輸問題;使用二進位制流或壓縮文字傳輸,減少了一部分稀疏編碼帶來的位元組空洞,提高了資訊密度。傳輸速度更快,資料量更小,不僅降低成本,而且可以減少延遲。
2.可靠一致的API設計
客戶端服務端使用相同的原檔案進行介面定義,雙方介面暴露完全相同,一致性更強,相較於傳統的招搖介面管理,其資料結構更加直觀精確,不再需要維護介面-URL間的複雜對應關係,API升級管理更加簡單
3.對傳輸基礎設施無感知的通訊協議
節儉不能推出類似gRPCweb的方案的原因也正在於此.Thrift使用私有Tprotocol傳輸協議,與gRPC的HTTP / 2相比起來通用性大打折扣,Nginx的在最新的穩定版中已經提供了grpc_pass負載均衡支援,我們可以無痛使用原有的四層/七層負載均衡器提供大規模的呼叫支援
4.高效的序列化/反序列化支援
gRPC相較於JSON,擁有更高的序列化/反序列化效率,易於實現更高的吞吐效能
2gRPC web能不能用?好不好用?
話不多說,接下來我們就開始進行一套gRPCserver + envoy代理+ gRPCweb on TypeScript的echo通訊測試,作為對比,筆者將實現一套同樣功能的websocket鏈路,用以測試雙方通訊效能,比較這些功能的實現難度並評價兩種“看似比較底層”的網路通訊協議。
首先定義一個我們的回聲服務的原型:
syntax = "proto3";package chatman;
message ChatRequest {
string messages = 1;
}
message ChatResponse {
string messages = 1;
}
service Chat { rpc chat (ChatRequest) returns (ChatResponse);
}
然後寫伺服器端程式碼,此處使用的Python實現:
生成伺服器端的protobuf的檔案,使用gRPC工具生成程式碼即可,然後我們引入grpcio和這些protobuf的庫檔案:
import grpcimport service_pb2,service_pb2_grpc
from concurrent.futures import ThreadPoolExecutorimport time
class ChatServicer(service_pb2_grpc.ChatServicer):
def chat(self,request,context): print(request.messages)
return service_pb2.ChatResponse(messages="Server Received: %s" % request.messages)def server_start():
server = grpc.server(ThreadPoolExecutor(max_workers=5))
service_pb2_grpc.add_ChatServicer_to_server(ChatServicer(),server)
server.add_insecure_port('0.0.0.0:8800')
server.start()
time.sleep(3600*24)if __name__ == '__main__':
server_start()
我們先測試下HTTP / 2二進位制流模式的gRPC:
Python的程式碼如下:
import grpcimport service_pb2_grpcimport service_pb2
channel = grpc.insecure_channel('0.0.0.0:8800')
stub = service_pb2_grpc.ChatStub(channel)
message = service_pb2.ChatRequest(messages="test message")
msg = stub.chat(message)
print(msg)
返回訊息:“Server Received:test message”。測試成功,抓包結果如下:
可以看到,兩方使用“不安全“的HTTP協議交換了資料,通訊成功完成。
接下來,我們使用gRPC的web實現相同功能。值得注意的一點是,目前gRPC幅還不能直接執行在瀏覽器上,因為瀏覽器尚未提供裸HTTP協議的介面,因此需要進行一層簡單的封裝,並透過代理剝去這層封裝才能與真正的gRPC後端通訊,這種通訊方式被稱為gRPC的Web文字。
同理,使用gRPC的工具生成打字稿檔案,生成檔案包含一個原始的JS庫,一個描述檔案以及一個TS客戶端庫,編寫程式碼:
import { ChatRequest,ChatResponse } from './service_pb'import { ChatClient } from './ServiceServiceClientPb'const client1 = new ChatClient(",{},{});
let req = new ChatRequest()
req.setMessages("messages")
client1.chat(req,{},(err: any, res)=>{
console.log(res);
});
在HTML中直接引用這個JS,並使用特使代理進行gRPC的Web文字到gRPC協議的轉換,配置如下:
admin:
access_log_path: /tmp/admin_access.log
address:
socket_address: { address: 127.0.0.1, port_value: 9901 }
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 127.0.0.1, port_value: 8080 }
filter_chains:
- filters:
- name: envoy.http_connection_manager
config:
codec_type: auto
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match: { prefix: "/" }
route:
cluster: echo_service
max_grpc_timeout: 0s
cors:
allow_origin:
- "*"
allow_methods: GET, PUT, DELETE, POST, OPTIONS
allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
max_age: "1728000"
expose_headers: custom-header-1,grpc-status,grpc-message
enabled: true
http_filters:
- name: envoy.grpc_web
- name: envoy.cors
- name: envoy.router
clusters:
- name: echo_service
connect_timeout: 0.25s
type: logical_dns
http2_protocol_options: {}
lb_policy: round_robin
hosts: [{ socket_address: { address: 127.0.0.1, port_value: 8800 }}]
現在進行測試,訪問剛才的網頁,可以看到通訊情況:
一看就知道是的base64編碼,果斷解碼:
果然不出所料,是一個封裝在HTTP裡的HTTP通訊
接下來,使用的WebSocket進行對比:
編寫服務端程式:
console.log("Server started");
var Msg = '';
var WebSocketServer = require('ws').Server
, wss = new WebSocketServer({port: 8010});
wss.on('connection', function(ws) {
ws.on('message', function(message) {
console.log('Received: %s', message);
ws.send('Server received: ' + message);
});
});
使用節點啟動後,在瀏覽器的控制檯裡連線並訪問:
const ws_echo = new WebSocket("ws://127.0.0.1:8081/")
ws_echo.addEventListener('message', (event) => {
console.log(event.data);
})
ws_echo.send("Hello!")
控制檯返回伺服器收到:您好!
通訊完成,檢視協議:
可以看到,經過一次通訊後,伺服器直接返回升級升級連線的報頭,隨後雙方使用的WebSocket進行通訊,比起gRPC的協議,更加簡易直白。
在測試前我一直在思考,gRPCweb究竟是一個怎樣的存在第一眼看到gRPCweb文字這個詞,我的第一感覺是這個?
在Gmail的郵箱裡,充滿了這種極其類似的protobuf的XHR請求,當看到需要使用專用代理進行轉發的時候,我一度以為是這種高度壓縮的文字協議正式出現在了通用的框架裡,然而事實是,不論是gRPC-web還是gRPCweb-text,不論是易用性還是請求響應體長度,比起jon over brotli over websocket都仍然有很大的進步空間,要實現透過CDN分發js節省API伺服器頻寬的構思目前仍然需要自己造輪子,gRPCweb並不是銀彈,至少目前不是。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559359/viewspace-2637227/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- gRPC-網路現狀及測試RPC
- 測試行業現狀分析行業
- 移動app測試現狀全面剖析APP
- 博弈論之大話測試行業現狀行業
- 聊聊軟體測試崗位的招聘現狀
- 近年來測試行業現狀與趨勢 2行業
- JUnit5的條件測試、巢狀測試、重複測試巢狀
- CSRF漏洞復現及測試工具講解
- 測試管理及測試工具盒集
- 近年來軟體測試行業現狀與趨勢行業
- 巢狀表的測試(一)巢狀
- 巢狀表的測試(二)巢狀
- 網路空間測繪國內外發展及現狀
- 黑盒測試策略及測試範圍(web端)Web
- android 單元測試出現錯誤及改正Android
- C++ 巢狀類簡單測試C++巢狀
- 測試案例分享:淘寶網使用者體驗測試出現的8個問題及測試方法公開
- 前端單元測試總結及測試工具介紹前端
- 如何實現介面異常場景測試?測試方法探索與測試工具實現
- JavaScript單元測試及原理JavaScript
- 常見埠及安全測試
- kaldi 的安裝及測試
- SpringStateMachine狀態機之八-整合測試SpringMac
- 測試測試測試測試測試測試
- oracle中number型欄位長度、精度及實際儲存狀態測試(zt)Oracle
- oracle例項、資料庫及相關資料庫狀態的理解和測試Oracle資料庫
- 2015年電子商務行業薪酬現狀及預測行業
- AI晶片市場現狀及企業競爭狀況AI晶片
- 雲端計算應用現狀及需求
- 文生影片: 任務、挑戰及現狀
- 幾種移動廣告現狀及前景
- fixtrue基礎之測試初始化及測試後清理操作
- Rust效能分析之測試及火焰圖,附(lru,lfu,arc)測試Rust
- 2017測試行業狀況報告行業
- 軟體測試技術及工具
- griffin環境搭建及功能測試
- Alluxio+HDFS+MapReduce整合及測試UX
- 【DG】搭建(二)及相關測試