国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Thrift 序列化協議淺析

原創 精選
開源
Thrift 是 Facebook 開源的一個高性能,輕量級 RPC 服務框架,是一套全棧式的 RPC 解決方案,包含序列化與服務通信能力,并支持跨平臺/跨語言。

作者| 楊晨曦

背景

Thrift 是 Facebook 開源的一個高性能,輕量級 RPC 服務框架,是一套全棧式的 RPC 解決方案,包含序列化與服務通信能力,并支持跨平臺/跨語言。整體架構如圖所示:

圖片

Thrift 軟件棧定義清晰,各層的組件松耦合、可插拔,能夠根據業務場景靈活組合,如圖所示:

圖片

Thrift 本身是一個比較大的話題,這篇文章不會涉及到全部內容,只會涉及到其中的序列化協議。

圖片

協議原理

Binary 協議

消息格式

這里通過一個示例對 Binary 消息格式進行直觀的展示,IDL 定義如下:

// 接口
service SupService {
SearchDepartmentByKeywordResponse SearchDepartmentByKeyword(
1: SearchDepartmentByKeywordRequest request)
}

// 請求
struct SearchDepartmentByKeywordRequest {
1: optional string Keyword
2: optional i32 Limit
3: optional i32 Offset
}

// 假設request的payload如下:
{
Keyword: "lark",
Limit: 50,
Offset: nil,
}
編碼簡圖

圖片

編碼具體內容
抓包拿到編碼后的字節流(轉成了十進制,方便大家看)

/* 接口名長度 */ 0 0 0 25
/* 接口名 */ 83 101 97 114 99 104 68 101 112 97 114 116
109 101 110 116 66 121 75 101 121 119 111
114 100
/* 消息類型 */ 1
/* 消息序號 */ 0 0 0 1
/* keyword 字段類型 */ 11
/* keyword 字段ID*/ 0 1
/* keyword len */ 0 0 0 4
/* keyword value */ 108 97 114 107
/* limit 字段類型 */ 8
/* limit 字段ID*/ 0 2
/* limit value */ 0 0 0 50
/* 字段終止符 */ 0
編碼含義

消息頭

  • msg_type:消息類型,包含四種類型
  • Call:客戶端消息。調用遠程方法,并且期待對方發送響應。
  • OneWay:客戶端消息。調用遠程方法,不期待響應。
  • Reply:服務端消息。正常響應。
  • Exception:服務端消息。異常響應。
  • msg_seq_id:消息序號。客戶端使用消息序號來處理響應的失序到達,實現請求和響應的匹配。服務端不需要檢查該序列號,也不能對序列號有任何的邏輯依賴,只需要響應的時候將其原樣返回即可。

消息體

消息體分為兩種編碼模式:

  1. 定長類型 -> T-V 模式,即:字段類型 + 序號 + 字段值
  2. 變長類型 -> T-L-V 模式,即:字段類型 + 序號 + 字段長度 + 字段值
  • field_type:字段類型,包括 String、I64、Struct、Stop 等。字段類型有兩個作用:
  • Stop 類型用于停止嵌套解析
  • 非 Stop 類型用于 Skip(Skip 操作是跳過當前字段,會在「常見問題 - 兼容性」進行講解)
  • fied_id:字段序號,解碼時通過序號確定字段
  • len:字段長度,用于變長類型,如 String
  • value:字段值

數據格式

1. 定長數據類型

數據類型

類型標識(8 位)

類型尺寸(單位:字節)

bool

2

1

byte

3

1

double

4

8

i16

6

2

i32

8

4

i64

10

8

2. 變長數據類型

數據類型

類型標識(8 位)

類型尺寸(長度 + 值)

string

11

4 + N

struct

12

嵌套數據 + 一個字節停止符(0)

map

13

1 + 1 + 4 + N*(X+Y) 【key 類型 + val 類型 + 長度 + 值】

set

14

1 + 4 + N 【val 類型 + 長度 + 值】

list

15

1 + 4 + N 【val 類型 + 長度 + 值】

其他協議

Compact 協議

Compact 協議是二進制壓縮協議,在大部分字段的編碼方式上與 Binary 協議保持一致。區別在于整數類型(包括變長類型的長度)采用了【先 zigzag 編碼 ,再 varint 壓縮編碼】實現,最大化節省空間開銷。

那么問題來了,varint 和 zigzag 是什么?

varint 編碼

解決的問題:定長存儲的整數類型絕對值較小時空間浪費大

據統計,RPC 通信時大部分時候傳遞的整數值都很小,如果使用定長存儲會很浪費。

舉個 ??,對 i32 類型的 7 進行編碼,可以說前面 3 個字節都浪費了:

00000000 00000000 00000000 00000111

解決思路:將整數類型由定長存儲轉為變長存儲(能用 1 個字節存下就堅決不用 2 個字節)

原理并不復雜,就是將整數按 7bit 分段,每個字節的最高位作為標識位,標識后一個字節是否屬于該數據。1 代表后面的字節還是屬于當前數據,0 代表這是當前數據的最后一個字節。

以 i32 類型,數值 955 為例,可以看出,由原來的 4 字節壓縮到了 2 字節:

binary編碼:       00000000  00000000  00000011  10111011
切分: 0000 0000000 0000000 0000111 0111011
compact編碼: 00000111 10111011

當然,varint 編碼同樣存在缺陷,那就是存儲大數的時候,反而會比 binary 的空間開銷更大:本來 4 個字節存下的數可能需要 5 個字節,8 個字節存下的數可能需要 10 個字節。

zigzag 編碼

解決的問題:絕對值較小的負數經過 varint 編碼后空間開銷較大 舉個 ??,i32 類型的負數(-11)

原碼:         10000000  00000000  00000000  00001011
反碼: 11111111 11111111 11111111 11110100
補碼: 11111111 11111111 11111111 11110101
varint編碼: 00001111 11111111 11111111 11111111 11110101

顯然,對于絕對值較小的負數,用 varint 編碼以后前導 1 過多,難以壓縮,空間開銷比 binary 編碼還大。

解決思路:負數轉正數,從而把前導 1 轉成前導 0,便于 varint 壓縮

算法公式 & 步驟 & 示范:

// 算法公式
32位: (n << 1) ^ (n >> 31)
64位: (n << 1) ^ (n >> 63)


/*
* 算法步驟:
* 1. 不分正負:符號位后置,數值位前移
* 2. 對于負數:符號位不變,數值位取反
*/


// 示例
負數(-11)
補碼: 11111111 11111111 11111111 11110101
符號位后置,數值位前移: 11111111 11111111 11111111 11101011
符號位不變,數值位取反(21): 00000000 00000000 00000000 00010101

正數(11)
補碼: 00000000 00000000 00000000 00010101
符號位后置,數值位前移(22): 00000000 00000000 00000000 00101010

【奇怪的知識】為什么取名叫 zigzag?

因為這個算法將負數編碼成正奇數,正數編碼成偶數。最后效果是正負數穿插向前,就像這樣:

編碼前       編碼后
0 0
-1 1
1 2
-2 3
2 4

Json 協議

Thrift 不僅支持二進制序列化協議,也支持 Json 這種文本協議

數據格式

/* bool、i8、i16、i32、i64、double、string */
"編號": {
"類型": "值"
}
// 示例
"1": {
"str": "keyword"
}


/* struct */
"編號": {
"rec": {
"成員編號": {
"成員類型": "成員值"
},
...
}
}
// 示例
"1": {
"rec": {
"1": {
"i32": 50
}
}
}


/* map */
"編號": {
"map": [
"鍵類型",
"值類型",
元素個數,
"鍵1",
"值1",
...
"鍵n",
"值n"
]
}
// 示例
"6": {
"map": [
"i64",
"str",
1,
666,
"mapValue"
]
}


/* List */
"編號": {
"set/lst": [
"值類型",
元素個數,
"ele1",
"ele2",
"elen"
]
}
// 示例
"2": {
"lst": [
"str",
2,
"lark","keyword"]
}

case 分析

修改字段類型導致 RPC 超時

現象:A 服務訪問 B 服務,業務邏輯短時間處理完,但整個請求 15s 超時,必現。

直接原因:IDL 類型被修改;并且只升級了服務端(B 服務),沒升級客戶端(A 服務)

圖片

本質原因:string 是變長編碼,i64 是定長編碼。由于客戶端沒有升級,所以反序列化的時候,會把 signTime 當做 string 類型來解析。而變長編碼是 T-L-V 模式,所以解析的時候會把 signTime 的低位 4 字節翻譯成 string 的 length。

signTime 是時間戳,大整數,比如:1624206147902,轉成二進制為:

00000000 00000000 00000001 01111010 00101010 00111011 00000001 00111110

低位 4 字節轉成十進制為:378

也就是要再讀 378 個字節作為 SignTime 的值,這已經超過了整個 payload 的大小,最終導致 Socket 讀超時。

【注】修改類型不一定就會導致超時,如果 value 的值比較小,解析到的 length 也比較小,能夠保證讀完。但是錯誤的解析可能會導致各種預期之外的情況,包括:

  1. 亂碼
  2. 空值
  3. 報錯:unknown data type xxx (skip 異常)

常見問題

兼容性

增加字段

通過 skip 來跳過增加的字段,從而保證兼容性

圖片

刪除字段

編譯生成的解析代碼是基于 field_id 的 switch-case 結構,語法結構上直接具備兼容性。

圖片

修改字段名

不破壞兼容性,因為 binary 協議不會對 name 進行編碼

Exception

Thrift 有兩種 Exception,一種是框架內置的異常,一種是 IDL 自定義的異常。

框架內置的異常包括:「方法名錯誤」、「消息序列號錯誤」、「協議錯誤」,這些異常由框架捕獲并封裝成 Exception 消息,反序列化時會轉成 error 并拋給上層,邏輯如下:

圖片

另一種異常是由用戶在 IDL 中自定義的,關鍵字是 exception,用法上跟 struct 沒有太大區別。

圖片

optional、require 實現原理

optional 表示字段可填,require 表示必填

字段被標識為 optional 之后:

  • 基本類型會被編譯為指針類型
  • 序列化代碼會做空值判斷,如果字段為空,則不會被編碼

字段被標識為 require 之后:

  • 基本類型會被編譯為非指針類型(復合類型 optional 和 require 沒區別)
  • 序列化不會做空值判斷,字段一定會被編碼。如果沒有顯式賦值,就編碼默認值(默認空值,或者 IDL 顯式指定的默認值)?
責任編輯:未麗燕 來源: 字節跳動技術團隊
相關推薦

2009-09-09 14:45:41

XML序列化和反序列化

2009-09-09 15:54:48

C# XML序列化

2009-08-25 14:59:39

C# XML序列化應用

2009-09-09 16:53:49

C# XmlSeria序列化

2009-09-09 17:14:24

XML序列化

2009-08-25 15:15:08

C#對象序列化應用

2022-08-06 08:41:18

序列化反序列化Hessian

2011-06-01 15:05:02

序列化反序列化

2009-08-24 17:14:08

C#序列化

2018-03-19 10:20:23

Java序列化反序列化

2023-12-13 13:49:52

Python序列化模塊

2009-08-06 11:16:25

C#序列化和反序列化

2011-05-18 15:20:13

XML

2013-03-11 13:55:03

JavaJSON

2009-08-25 14:24:36

C#序列化和反序列化

2011-06-01 14:50:48

2009-06-14 22:01:27

Java對象序列化反序列化

2019-11-20 10:07:23

web安全PHP序列化反序列化

2011-06-01 14:26:11

序列化

2021-11-18 07:39:41

Json 序列化Vue
點贊
收藏

51CTO技術棧公眾號

午夜精品久久久久久毛片| 日韩夫妻性生活xx| 欧美亚洲综合久久| gogo高清免费视频| 久久久久久电影| 中文字幕制服丝袜在线| 亚洲激情婷婷| 91丨九色丨国产在线| 美女福利一区| 欧美精品在线免费播放| 欧美日韩五区| 亚洲日韩中文字幕| 7777kkk亚洲综合欧美网站| 欧美区在线观看| 欧洲毛片在线| 色狠狠av一区二区三区| 四虎影视精品成人| 欧美性猛交xxxx乱大交3| 黄色网免费看| 亚洲午夜精品网| 91欧洲在线视精品在亚洲| 亚洲综合色丁香婷婷六月图片| 99re精彩视频| 一区二区在线观看免费| 在线看的你懂得| 色综合激情久久| 思思99re6国产在线播放| 欧美性欧美巨大黑白大战| 色视频在线观看福利| 在线观看一区日韩| 91黄色在线| 伊人久久男人天堂| 草莓视频一区二区三区| 久久久久久av无码免费网站下载| 一区二区在线视频| 国产不卡网站| 精品视频久久久久久久| 男人天堂资源在线| 佐佐木明希av| 久久黄色级2电影| 深田咏美在线x99av| 美腿丝袜亚洲色图| 欧美xxxx吸乳| 99久久精品情趣| 欧美成年人视频在线观看| 综合久久一区二区三区| а√天堂www在线а√天堂视频| 午夜激情一区二区三区| 国产精品视频一区二区久久| 欧美不卡一二三| 日韩天堂在线| 国模精品系列视频| 日韩精品一区二区久久| 欧美成ee人免费视频| 国产一区美女在线| 九九视频精品在线观看| 亚洲一区二区3| 超碰97在线免费观看| 日韩av网址在线观看| 日韩精品成人在线观看| 国产美女91呻吟求| 免费亚洲视频| 成人在线观看黄| 色吊一区二区三区| 欧美日韩精品免费观看视完整| 91国内免费在线视频| 欧美福利在线| 成人污网站在线观看| 亚洲天堂福利av| av免费在线观看网址| 欧美精品中文字幕一区| 天天插综合网| 日本a在线天堂| 亚洲国产cao| 久久久人成影片一区二区三区在哪下载 | 欧美军人男男激情gay| 欧美日韩在线播放一区二区| 成人一区二区在线观看| av超碰在线| 亚洲性夜色噜噜噜7777| 国产精品99久久精品| 国产玉足脚交久久欧美| 午夜在线电影亚洲一区| 爱啪啪综合导航| 成人国产精品久久久久久亚洲| 亚洲免费综合| 色视频网站在线| 日韩精品极品毛片系列视频| 国语产色综合| 国产成人无码a区在线观看视频| 欧美视频一区二| 国产精品三级| 色综合av综合无码综合网站| 精品福利一二区| 三级电影一区| 91国产精品视频在线观看| 亚洲成人av在线| 欧美久久成人| 美女视频黄a视频全免费观看| 最近日韩中文字幕中文| 久久精品主播| 你懂的好爽在线观看| 91精品国产高清久久久久久91| 久久国产精品免费| 蜜桃av在线免费观看| 国产精品亚洲欧美导航| 国产精品午夜久久| 久久精品女人天堂av免费观看 | 在线欧美日韩国产| 网曝91综合精品门事件在线| 野外做受又硬又粗又大视频√| 欧美一区二区久久久| 91麻豆精品国产91久久久平台| 9l视频白拍9色9l视频| 在线看日韩欧美| 国产一区二区中文字幕| 欧美四级在线| 日韩一二三区不卡在线视频| 777亚洲妇女| 久久av在线| 丝袜美腿av在线| 日韩av一级大片| 欧美一区二区三区视频在线| 狠狠爱www人成狠狠爱综合网| 在线观看免费网站| 国产精品午夜一区二区欲梦| 亚洲欧洲日韩综合一区二区| 一区中文字幕电影| 国产精品-区区久久久狼| 夜夜嗨av色一区二区不卡| 国产伦精一区二区三区| 欧美一级鲁丝片| 国产又粗又大又爽的视频| 亚洲免费av电影| 成人av电影在线网| 91国产精品| 免费国产成人av| 欧美激情国内偷拍| 国产精品国产精品国产专区不蜜| 日韩一区免费| 国产网站免费观看| 国产欧美日韩最新| 91激情在线视频| 老**午夜毛片一区二区三区| 中文字幕在线三区| 正在播放一区| 久久精品91久久香蕉加勒比| 国产亚洲女人久久久久毛片| 思热99re视热频这里只精品| 中文资源在线网| 久久riav| 日韩高清欧美高清| 91在线观看视频| 噜噜噜狠狠夜夜躁精品仙踪林| 精精国产xxxx视频在线动漫| 成人国产精品一区| 在线不卡免费av| 精品夜夜嗨av一区二区三区| 亚洲福利影视| 全部a∨一极品视觉盛宴| 91高跟黑色丝袜呻吟在线观看| 制服丝袜亚洲网站| 韩国成人精品a∨在线观看| 先锋影音网一区二区| 波多野吉衣av| 国产精品日韩欧美一区二区三区| 欧美高清视频一二三区| 国产成人亚洲综合a∨婷婷| 欧美男人操女人视频| 黄视频在线观看免费| 天堂v在线视频| 久久久久久高潮国产精品视| 黑人巨大精品欧美一区二区免费| 日韩激情在线观看| jizz性欧美23| 91短视频版在线观看www免费| 免费一级淫片aaa片毛片a级| 国产精品美女999| 亚洲白拍色综合图区| 国产精品免费视频观看| av不卡在线| 日韩成人18| 免费在线观看黄色网| 国产美女无遮挡网站| 成人午夜在线视频一区| 亚洲男人天堂视频| 亚洲成人黄色影院| 国产酒店精品激情| 欧美www视频在线观看| 国产精品扒开腿做爽爽爽视频软件| 最近2018中文字幕免费在线视频| 欧美在线一二三区| 热久久免费视频精品| 日韩精品福利在线| 亚洲影院在线观看| 国产精品白丝av| 影音先锋国产精品| 精品一区二区男人吃奶| 国产粉嫩在线观看| 中日韩一区二区三区|