Java?Chassis3的多種序列化方式支持技術(shù)解密
打開一個簡單的 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
支持多序列化方式,需要實現(xiàn) HttpMessageConverter 接口,并在 Controller 聲明支持的 Content-Type。 如果使用 Spring Fox 或者 Spring Doc 等 Open API工具生成契約,契約內(nèi)容只會包含 Controller 聲明的序列化類型。 Spring Boot存在隱式的契約情況,這意味著契約并不能完全代表 Controller 服務(wù)的能力。 如果需要對接口增加或者減少序列化支持,都需要修改代碼。
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é)議族訪問微服務(wù), 只需要按照契約的描述構(gòu)造HTTP的報文。 在編碼側(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)請求在通信協(xié)議、序列化方式上的自動轉(zhuǎn)換。比如將HTTP協(xié)議轉(zhuǎn)Highway協(xié)議、application/json轉(zhuǎn)application/protobuf等。
基于 Java Chassis Benchmark ,做一個簡單性能測試。該測試對比了兩種場景:

場景一的默認(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)境的描述。下表的平均時延統(tǒng)計了測試客戶端計算的請求-響應(yī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è)務(wù)時延比較大(>100ms)的時候, 序列化的時延可以忽略。
不同的序列化方式除了性能差異,在可維護(hù)方面也會存在很大的差異。比如 proto-buffer 在兼容性方面的表現(xiàn)會比 json 差,當(dāng)修改接口定義的時候, 比如增加屬性、刪除屬性、修改屬性等,proto-buffer 更容易導(dǎo)致兼容性問題,做好兼容性防范對多數(shù)用戶而言,都是比較困難的事情。
支持多協(xié)議、多序列化方式的另外一個考慮,是對接遺留系統(tǒng)。對接遺留系統(tǒng)會背負(fù)大量歷史債務(wù),使得新系統(tǒng)本身設(shè)計偏離預(yù)期的方向。在 Java Chassis 多序列化方式的選擇上, 只提供了目前廣泛使用的 json 和 proto-buffer 支持, 而沒有選擇支持其他序列化方案。 以架構(gòu)的韌性去處理遺留系統(tǒng)問題,是 Java Chassis堅持的一個重要設(shè)計理念,對接遺留系統(tǒng)或者保持與遺留系統(tǒng)的兼容,不是它的主要設(shè)計目標(biāo)。

在序列化方式選擇上,簡單的總結(jié)如下:
- 使用
REST協(xié)議是絕大多數(shù)場景的最優(yōu)選擇,能夠最好的兼顧性能、可靠性、韌性等方面的要求。 - 對于數(shù)據(jù)量比較大,業(yè)務(wù)時延很低(<100ms),并且業(yè)務(wù)比較穩(wěn)定,業(yè)務(wù)接口不需要頻繁變動的場景,可以采用
proto-buffer來優(yōu)化性能,按需調(diào)整。
客戶故事:某個客戶的關(guān)鍵核心系統(tǒng)對于時延要求很高,因此需要采用私有協(xié)議和序列化方式來提升性能。但是對于一些非核心系統(tǒng),需要使用REST接口,方便日常開發(fā)、調(diào)試。Java Chassis的解耦設(shè)計使得客戶無需對代碼進(jìn)行任何改造,就可以滿足兩方面的要求。
以上就是Java Chassis 3多種序列化方式支持技術(shù)解密的詳細(xì)內(nèi)容,更多關(guān)于Java Chassis3序列化方式的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Spring事務(wù)失效的一種原因關(guān)于this調(diào)用的問題
這篇文章主要介紹了Spring事務(wù)失效的一種原因關(guān)于this調(diào)用的問題,本文給大家分享問題原因及解決辦法,通過實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-10-10
深入理解Mybatis中的resultType和resultMap
這篇文章給大家介紹了mybatis中的resultType和resultMap的用法實例講解,MyBatis中在查詢進(jìn)行select映射的時候,返回類型可以用resultType,也可以用resultMap,至于兩種用法區(qū)別,通過本文一起學(xué)習(xí)吧2016-09-09
spring security中的csrf防御原理(跨域請求偽造)
這篇文章主要介紹了spring security中的csrf防御機(jī)制原理解析(跨域請求偽造),本文通過實例代碼詳解的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12
Java?ArrayList實現(xiàn)刪除指定位置的元素
目標(biāo):list中有0到39共40個元素,刪除其中索引是10、20、30的元素。本文為大家整理了三個不同的方法,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-01-01
解決IDEA集成Docker插件后出現(xiàn)日志亂碼的問題
這篇文章主要介紹了解決IDEA集成Docker插件后出現(xiàn)日志亂碼的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11

