Java?Chassis3的多種序列化方式支持技術解密
打開一個簡單的 REST 接口
@RestSchema(schemaId = "ProviderController") @RequestMapping(path = "/") public class ProviderController { @PostMapping("/benchmark") public DataModel sayHello(@RequestHeader("wait") int wait, @RequestBody DataModel dataModel) { if (wait > 0) { Thread.sleep(wait); } return dataModel; } }
契約
openapi: 3.0.1 info: title: swagger definition for org.apache.servicecomb.samples.ProviderController version: 1.0.0 servers: - url: / paths: /benchmark: post: operationId: sayHello parameters: - name: wait in: header required: true schema: type: integer format: int32 requestBody: content: application/json: schema: $ref: '#/components/schemas/DataModel' application/protobuf: schema: $ref: '#/components/schemas/DataModel' text/plain: schema: $ref: '#/components/schemas/DataModel' required: true x-name: dataModel responses: "200": description: response of 200 content: application/json: schema: $ref: '#/components/schemas/DataModel' application/protobuf: schema: $ref: '#/components/schemas/DataModel' text/plain: schema: $ref: '#/components/schemas/DataModel' components: schemas: ChildDataModel: type: object properties: numInt: type: integer format: int32 numLong: type: integer format: int64 numDouble: type: number format: double numFloat: type: number format: float data: type: string x-java-class: org.apache.servicecomb.samples.ChildDataModel DataModel: type: object properties: data: type: object additionalProperties: $ref: '#/components/schemas/ChildDataModel' x-java-class: org.apache.servicecomb.samples.DataModel
可以看到 Java Chassis使用了Open API 3.0.1的協(xié)議規(guī)范,Request Body
和 responses
增加了 application/protobuf
、 text/plain
的支持。 這種使用形式,奠定了Java Chassis 3多序列化支持方式的基礎,細心的讀者應該很快能夠發(fā)現(xiàn)這種方式與其他支持多序列化框架之間的差異。
Spring Boot
支持多序列化方式,需要實現(xiàn) HttpMessageConverter
接口,并在 Controller
聲明支持的 Content-Type
。 如果使用 Spring Fox
或者 Spring Doc
等 Open API工具生成契約,契約內(nèi)容只會包含 Controller
聲明的序列化類型。 Spring Boot存在隱式的契約情況,這意味著契約并不能完全代表 Controller
服務的能力。 如果需要對接口增加或者減少序列化支持,都需要修改代碼。
Dubbo
Dubbo 需要在 Provider 使用 dubbo:protocol
聲明序列化方式, 在Consumer使用 dubbo:reference
聲明序列化方式。 由于 Dubbo 是基于IDL
的契約系統(tǒng), 在使用 RPC 的場景下,可以通過配置動態(tài)調(diào)整序列化方式。 REST
支持在 Dubbo 是完全獨立的單元, 序列化方式也獨立于 RPC 接口, RPC
和 REST
不能互操作。
Open API基于 REST
的語義,來支持 IDL
的語義。 Java Chassis能夠更加直觀的支持通過第三方工具以HTTP協(xié)議族訪問微服務, 只需要按照契約的描述構造HTTP的報文。 在編碼側, Java Chassis的客戶端可以使用 REST 語義的接口,如 RestOperations
,也可以使用 RPC 語義的接口訪問服務端。
定義服務端接口
public interface ProviderService { DataModel sayHello(int wait, DataModel dataModel); }
通過RPC訪問
@RestSchema(schemaId = "ConsumerController") @RequestMapping(path = "/") public class ConsumerController { @RpcReference(schemaId = "ProviderController", microserviceName = "provider") private ProviderService providerService; @PostMapping("/benchmark") public DataModel sayHello(@RequestHeader("wait") int wait, @RequestBody DataModel dataModel) { return providerService.sayHello(wait, dataModel); } }
Java Chassis以OpenAPI為基礎的Edge Service部件,能夠?qū)崿F(xiàn)請求在通信協(xié)議、序列化方式上的自動轉換。比如將HTTP協(xié)議轉Highway協(xié)議、application/json轉application/protobuf等。
基于 Java Chassis Benchmark ,做一個簡單性能測試。該測試對比了兩種場景:
場景一的默認配置:
servicecomb: rest: parameter: default-request-encoding: "application/json" default-response-encoding: "application/json"
場景二的默認配置:
servicecomb: rest: parameter: default-request-encoding: "application/protobuf" default-response-encoding: "application/protobuf"
測試結果參考下表。該數(shù)據(jù)主要用于說明序列化差異,因此省去了測試環(huán)境的描述。下表的平均時延統(tǒng)計了測試客戶端計算的請求-響應時間的平均值。
版本 | 數(shù)據(jù)單位 | 等待時間 | 線程數(shù) | 執(zhí)行次數(shù) | 執(zhí)行時間 | 平均時延 |
---|---|---|---|---|---|---|
protobuffer | 1 | 0 | 10 | 1000 | 6642 | 6 |
protobuffer | 100 | 0 | 10 | 1000 | 9418 | 9 |
protobuffer | 1000 | 0 | 10 | 1000 | 25205 | 24 |
protobuffer | 1 | 10 | 10 | 1000 | 15432 | 15 |
protobuffer | 100 | 10 | 10 | 1000 | 15965 | 15 |
protobuffer | 1000 | 10 | 10 | 1000 | 25926 | 25 |
protobuffer | 1 | 100 | 10 | 1000 | 105727 | 105 |
protobuffer | 100 | 100 | 10 | 1000 | 106376 | 106 |
protobuffer | 1000 | 100 | 10 | 1000 | 114452 | 114 |
jason | 1 | 0 | 10 | 1000 | 6736 | 6 |
jason | 100 | 0 | 10 | 1000 | 15063 | 14 |
jason | 1000 | 0 | 10 | 1000 | 69757 | 68 |
jason | 1 | 10 | 10 | 1000 | 16632 | 16 |
jason | 100 | 10 | 10 | 1000 | 20033 | 19 |
jason | 1000 | 10 | 10 | 1000 | 66104 | 65 |
jason | 1 | 100 | 10 | 1000 | 104868 | 104 |
jason | 100 | 100 | 10 | 1000 | 107439 | 107 |
jason | 1000 | 100 | 10 | 1000 | 132786 | 131 |
從這組數(shù)據(jù)可以看出:
- 在數(shù)據(jù)量比較小的場景下,使用
json
和proto-buffer
性能差異很小。 在數(shù)據(jù)量比較大的情況下,proto-buffer
的性能明顯好于json
。 - 在業(yè)務時延比較大(>100ms)的時候, 序列化的時延可以忽略。
不同的序列化方式除了性能差異,在可維護方面也會存在很大的差異。比如 proto-buffer
在兼容性方面的表現(xiàn)會比 json
差,當修改接口定義的時候, 比如增加屬性、刪除屬性、修改屬性等,proto-buffer
更容易導致兼容性問題,做好兼容性防范對多數(shù)用戶而言,都是比較困難的事情。
支持多協(xié)議、多序列化方式的另外一個考慮,是對接遺留系統(tǒng)。對接遺留系統(tǒng)會背負大量歷史債務,使得新系統(tǒng)本身設計偏離預期的方向。在 Java Chassis 多序列化方式的選擇上, 只提供了目前廣泛使用的 json
和 proto-buffer
支持, 而沒有選擇支持其他序列化方案。 以架構的韌性去處理遺留系統(tǒng)問題,是 Java Chassis堅持的一個重要設計理念,對接遺留系統(tǒng)或者保持與遺留系統(tǒng)的兼容,不是它的主要設計目標。
在序列化方式選擇上,簡單的總結如下:
- 使用
REST
協(xié)議是絕大多數(shù)場景的最優(yōu)選擇,能夠最好的兼顧性能、可靠性、韌性等方面的要求。 - 對于數(shù)據(jù)量比較大,業(yè)務時延很低(<100ms),并且業(yè)務比較穩(wěn)定,業(yè)務接口不需要頻繁變動的場景,可以采用
proto-buffer
來優(yōu)化性能,按需調(diào)整。
客戶故事:某個客戶的關鍵核心系統(tǒng)對于時延要求很高,因此需要采用私有協(xié)議和序列化方式來提升性能。但是對于一些非核心系統(tǒng),需要使用REST接口,方便日常開發(fā)、調(diào)試。Java Chassis的解耦設計使得客戶無需對代碼進行任何改造,就可以滿足兩方面的要求。
以上就是Java Chassis 3多種序列化方式支持技術解密的詳細內(nèi)容,更多關于Java Chassis3序列化方式的資料請關注腳本之家其它相關文章!
相關文章
Spring事務失效的一種原因關于this調(diào)用的問題
這篇文章主要介紹了Spring事務失效的一種原因關于this調(diào)用的問題,本文給大家分享問題原因及解決辦法,通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下2021-10-10深入理解Mybatis中的resultType和resultMap
這篇文章給大家介紹了mybatis中的resultType和resultMap的用法實例講解,MyBatis中在查詢進行select映射的時候,返回類型可以用resultType,也可以用resultMap,至于兩種用法區(qū)別,通過本文一起學習吧2016-09-09spring security中的csrf防御原理(跨域請求偽造)
這篇文章主要介紹了spring security中的csrf防御機制原理解析(跨域請求偽造),本文通過實例代碼詳解的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12Java?ArrayList實現(xiàn)刪除指定位置的元素
目標:list中有0到39共40個元素,刪除其中索引是10、20、30的元素。本文為大家整理了三個不同的方法,感興趣的小伙伴可以跟隨小編一起學習一下2023-01-01解決IDEA集成Docker插件后出現(xiàn)日志亂碼的問題
這篇文章主要介紹了解決IDEA集成Docker插件后出現(xiàn)日志亂碼的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11