Java?Chassis3的多種序列化方式支持技術(shù)解密
打開一個(gè)簡單的 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多序列化支持方式的基礎(chǔ),細(xì)心的讀者應(yīng)該很快能夠發(fā)現(xiàn)這種方式與其他支持多序列化框架之間的差異。
Spring Boot
支持多序列化方式,需要實(shí)現(xiàn) HttpMessageConverter
接口,并在 Controller
聲明支持的 Content-Type
。 如果使用 Spring Fox
或者 Spring Doc
等 Open API工具生成契約,契約內(nèi)容只會(huì)包含 Controller
聲明的序列化類型。 Spring Boot存在隱式的契約情況,這意味著契約并不能完全代表 Controller
服務(wù)的能力。 如果需要對(duì)接口增加或者減少序列化支持,都需要修改代碼。
Dubbo
Dubbo 需要在 Provider 使用 dubbo:protocol
聲明序列化方式, 在Consumer使用 dubbo:reference
聲明序列化方式。 由于 Dubbo 是基于IDL
的契約系統(tǒng), 在使用 RPC 的場景下,可以通過配置動(dòng)態(tài)調(diào)整序列化方式。 REST
支持在 Dubbo 是完全獨(dú)立的單元, 序列化方式也獨(dú)立于 RPC 接口, RPC
和 REST
不能互操作。
Open API基于 REST
的語義,來支持 IDL
的語義。 Java Chassis能夠更加直觀的支持通過第三方工具以HTTP協(xié)議族訪問微服務(wù), 只需要按照契約的描述構(gòu)造HTTP的報(bào)文。 在編碼側(cè), Java Chassis的客戶端可以使用 REST 語義的接口,如 RestOperations
,也可以使用 RPC 語義的接口訪問服務(wù)端。
定義服務(wù)端接口
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以O(shè)penAPI為基礎(chǔ)的Edge Service部件,能夠?qū)崿F(xiàn)請(qǐng)求在通信協(xié)議、序列化方式上的自動(dòng)轉(zhuǎn)換。比如將HTTP協(xié)議轉(zhuǎn)Highway協(xié)議、application/json轉(zhuǎn)application/protobuf等。
基于 Java Chassis Benchmark ,做一個(gè)簡單性能測試。該測試對(duì)比了兩種場景:
場景一的默認(rèn)配置:
servicecomb: rest: parameter: default-request-encoding: "application/json" default-response-encoding: "application/json"
場景二的默認(rèn)配置:
servicecomb: rest: parameter: default-request-encoding: "application/protobuf" default-response-encoding: "application/protobuf"
測試結(jié)果參考下表。該數(shù)據(jù)主要用于說明序列化差異,因此省去了測試環(huán)境的描述。下表的平均時(shí)延統(tǒng)計(jì)了測試客戶端計(jì)算的請(qǐng)求-響應(yīng)時(shí)間的平均值。
版本 | 數(shù)據(jù)單位 | 等待時(shí)間 | 線程數(shù) | 執(zhí)行次數(shù) | 執(zhí)行時(shí)間 | 平均時(shí)延 |
---|---|---|---|---|---|---|
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è)務(wù)時(shí)延比較大(>100ms)的時(shí)候, 序列化的時(shí)延可以忽略。
不同的序列化方式除了性能差異,在可維護(hù)方面也會(huì)存在很大的差異。比如 proto-buffer
在兼容性方面的表現(xiàn)會(huì)比 json
差,當(dāng)修改接口定義的時(shí)候, 比如增加屬性、刪除屬性、修改屬性等,proto-buffer
更容易導(dǎo)致兼容性問題,做好兼容性防范對(duì)多數(shù)用戶而言,都是比較困難的事情。
支持多協(xié)議、多序列化方式的另外一個(gè)考慮,是對(duì)接遺留系統(tǒng)。對(duì)接遺留系統(tǒng)會(huì)背負(fù)大量歷史債務(wù),使得新系統(tǒng)本身設(shè)計(jì)偏離預(yù)期的方向。在 Java Chassis 多序列化方式的選擇上, 只提供了目前廣泛使用的 json
和 proto-buffer
支持, 而沒有選擇支持其他序列化方案。 以架構(gòu)的韌性去處理遺留系統(tǒng)問題,是 Java Chassis堅(jiān)持的一個(gè)重要設(shè)計(jì)理念,對(duì)接遺留系統(tǒng)或者保持與遺留系統(tǒng)的兼容,不是它的主要設(shè)計(jì)目標(biāo)。
在序列化方式選擇上,簡單的總結(jié)如下:
- 使用
REST
協(xié)議是絕大多數(shù)場景的最優(yōu)選擇,能夠最好的兼顧性能、可靠性、韌性等方面的要求。 - 對(duì)于數(shù)據(jù)量比較大,業(yè)務(wù)時(shí)延很低(<100ms),并且業(yè)務(wù)比較穩(wěn)定,業(yè)務(wù)接口不需要頻繁變動(dòng)的場景,可以采用
proto-buffer
來優(yōu)化性能,按需調(diào)整。
客戶故事:某個(gè)客戶的關(guān)鍵核心系統(tǒng)對(duì)于時(shí)延要求很高,因此需要采用私有協(xié)議和序列化方式來提升性能。但是對(duì)于一些非核心系統(tǒng),需要使用REST接口,方便日常開發(fā)、調(diào)試。Java Chassis的解耦設(shè)計(jì)使得客戶無需對(duì)代碼進(jìn)行任何改造,就可以滿足兩方面的要求。
以上就是Java Chassis 3多種序列化方式支持技術(shù)解密的詳細(xì)內(nèi)容,更多關(guān)于Java Chassis3序列化方式的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring事務(wù)失效的一種原因關(guān)于this調(diào)用的問題
這篇文章主要介紹了Spring事務(wù)失效的一種原因關(guān)于this調(diào)用的問題,本文給大家分享問題原因及解決辦法,通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-10-10Java實(shí)現(xiàn)藍(lán)橋杯G將軍的示例代碼
這篇文章主要介紹了Java實(shí)現(xiàn)藍(lán)橋杯G將軍的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02深入理解Mybatis中的resultType和resultMap
這篇文章給大家介紹了mybatis中的resultType和resultMap的用法實(shí)例講解,MyBatis中在查詢進(jìn)行select映射的時(shí)候,返回類型可以用resultType,也可以用resultMap,至于兩種用法區(qū)別,通過本文一起學(xué)習(xí)吧2016-09-09spring security中的csrf防御原理(跨域請(qǐng)求偽造)
這篇文章主要介紹了spring security中的csrf防御機(jī)制原理解析(跨域請(qǐng)求偽造),本文通過實(shí)例代碼詳解的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-12-12Java?ArrayList實(shí)現(xiàn)刪除指定位置的元素
目標(biāo):list中有0到39共40個(gè)元素,刪除其中索引是10、20、30的元素。本文為大家整理了三個(gè)不同的方法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-01-01解決IDEA集成Docker插件后出現(xiàn)日志亂碼的問題
這篇文章主要介紹了解決IDEA集成Docker插件后出現(xiàn)日志亂碼的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11