日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

涂鸦智能 dubbo-go 亿级流量的实践与探索

發布時間:2025/3/20 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 涂鸦智能 dubbo-go 亿级流量的实践与探索 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者 | 潘天穎,Github ID @pantianying,開源愛好者,就職于涂鴉智能

dubbo 是一個基于 Java 開發的高性能的輕量級 RPC 框架,dubbo 提供了豐富的服務治理功能和優秀的擴展能力。而 dubbo-go 在 java 與 golang 之間提供統一的服務化能力與標準,是涂鴉智能目前最需要解決的主要問題。本文分為實踐和快速接入兩部分,分享在涂鴉智能的 dubbo-go 實戰經驗,意在幫助用戶快速接入 dubbo-go RPC 框架,希望能讓大家少走些彎路。另外,文中的測試代碼基于 dubbo-go版本 v1.4.0。

dubbo-go 網關實踐

dubbo-go 在涂鴉智能的使用情況如上圖,接下來會為大家詳細介紹落地細節,希望這些在生產環境中總結的經驗能夠幫助到大家。

1. 背景

在涂鴉智能,dubbo-go 已經作為了 golang 服務與原有 dubbo 集群打通的首選 RPC 框架。其中比較有代表性的 open-gateway 網關系統(下文統一稱 gateway,開源版本見 https://github.com/dubbogo/dubbo-go-proxy)。該 gateway 動態加載內部 dubbo 接口信息,以HTTP API 的形式對外暴露。該網關意在解決上一代網關的以下痛點。

  • 通過頁面配置 dubbo 接口開放規則,步驟繁瑣,權限難以把控;
  • 接口非 RESTful 風格,對外部開發者不友好;
  • 依賴繁重,升級風險大;
  • 并發性能問題。

2. 架構設計

針對如上痛點,隨即著手準備設計新的 gateway 架構。首先就是語言選型,golang 的協程調用模型使得 golang 非常適合構建 IO 密集型的應用,且應用部署上也較 java 簡單。

經過調研后我們敲定使用 golang 作為 proxy 的編碼語言,并使用 dubbo-go 用于連接 dubbo provider 集群。provider 端的業務應用通過使用 java 的插件,以注解形式配置 API 配置信息,該插件會將配置信息和 dubbo 接口元數據更新到元數據注冊中心(下圖中的 redis )。這樣一來,配置從管理后臺頁面轉移到了程序代碼中。開發人員在編碼時,非常方便地看到 dubbo 接口對外的 API 描述,無需從另外一個管理后臺配置 API 的使用方式。

3. 實踐

從上圖可以看到,網關能動態加載 dubbo 接口信息,調用 dubbo 接口是基于 dubbo 泛化調用。泛化調用使 client 不需要構建 provider 的 interface 代碼,在 dubbo-go 中表現為無需調用 config.SetConsumerService 和 hessian.RegisterPOJO 方法,而是將請求模型純參數完成,這使得 client 動態新增、修改接口成為可能。在 apache / dubbo-sample / golang / generic / go-client 中的有泛化調用的演示代碼。

func test() {var appName = "UserProviderGer"var referenceConfig = config.ReferenceConfig{InterfaceName: "com.ikurento.user.UserProvider",Cluster: "failover",Registry: "hangzhouzk",Protocol: dubbo.DUBBO,Generic: true,}referenceConfig.GenericLoad(appName) // appName is the unique identification of RPCServicetime.Sleep(3 * time.Second)resp, err := referenceConfig.GetRPCService().(*config.GenericService).Invoke([]interface{}{"GetUser", []string{"java.lang.String"}, []interface{}{"A003"}})if err != nil {panic(err)} }

泛化調用的實現其實相當簡單。其功能作用在 dubbo 的 Filter 層中。Generic Filter 已經作為默認開啟的 Filter 加入到 dubbo Filter 鏈中。其核心邏輯如下:

func (ef *GenericFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {if invocation.MethodName() == constant.GENERIC && len(invocation.Arguments()) == 3 {oldArguments := invocation.Arguments()if oldParams, ok := oldArguments[2].([]interface{}); ok {newParams := make([]hessian.Object, 0, len(oldParams))for i := range oldParams {newParams = append(newParams, hessian.Object(struct2MapAll(oldParams[i])))}newArguments := []interface{}{oldArguments[0],oldArguments[1],newParams,}newInvocation := invocation2.NewRPCInvocation(invocation.MethodName(), newArguments, invocation.Attachments())newInvocation.SetReply(invocation.Reply())return invoker.Invoke(ctx, newInvocation)}}return invoker.Invoke(ctx, invocation) }

Generic Filter 將用戶請求的結構體參數轉化為統一格式的 map(代碼中的 struct2MapAll ),將類( golang 中為 struct )的正反序列化操作變成 map 的正反序列化操作。這使得無需 POJO 描述通過硬編碼注入 hessain 庫。

從上面代碼可以看到,泛化調用實際需要動態構建的內容有 4 個,ReferenceConfig 中需要的 InterfaceName、參數中的 method、ParameterTypes、實際入參 requestParams。

那么這些參數是如何從 HTTP API 匹配獲取到的呢?

這里就會用到上文提到的 provider 用于收集元數據的插件。引入插件后,應用在啟動時會掃描需要暴露的 dubbo 接口,將 dubbo 元數據和 HTTP API 關聯。插件使用方法大致如下,這里調了幾個簡單的配置作為示例,實際生產時注解內容會更多。

最終獲得的 dubbo 元數據如下:

{"key": "POST:/hello/{uid}/add","interfaceName": "com.tuya.hello.service.template.IUserServer","methodName": "addUser","parameterTypes": ["com.tuya.gateway.Context", "java.lang.String", "com.tuya.hello.User"],"parameterNames": ["context", "uid", "userInfo"],"updateTimestamp": "1234567890","permissionDO":{},"voMap": {"userInfo": {"name": "java.lang.String","sex": "java.lang.String","age": "java.lang.Integer"}},"parameterNameHumpToLine": true,"resultFiledHumpToLine": false,"protocolName": "dubbo",....... }

Gateway 從元數據配置中心訂閱到以上信息,就能把一個 API 請求匹配到一個 dubbo 接口。再從 API 請求中抓取參數作為入參。這樣功能就完成了流量閉環。

以上內容,大家應該對此 gateway 的項目拓撲結構有了清晰的認知。我接著分享項目在使用 dubbo-go 過程中遇到的問題和調優經驗。19 年初,當時的 dubbo-go 項目還只是構建初期,沒有什么用戶落地的經驗。我也是一邊參與社區開發,一邊編碼公司內部網關項目。在解決了一堆 hessain 序列化和 zookeeper 注冊中心的問題后,項目最終跑通了閉環。但是,作為一個核心應用,跑通閉環離上生產環境還有很長的路要走,特別是使用了當時穩定性待測試的新框架。整個測試加上功能補全,整整花費了一個季度的時間,直到項目趨于穩定,壓測效果也良好。單臺網關機器( 2C 8G )全鏈路模擬真實環境壓測達到 2000 QPS。由于引入了比較重的業務邏輯(單個請求平均調用 3 個 dubbo 接口),對于這個壓測結果,是符合甚至超出預期的。

總結了一些 dubbo-go 參數配置調優的經驗,主要是一些網絡相關配置。

大家在跑 demo 時,應該會看到配置文件最后有一堆配置,但如果對 dubbo-go 底層網絡模型不熟悉,就很難理解這些配置的含義。目前 dubbo-go 網絡層以 getty 為底層框架,實現讀寫分離和協程池管理。getty 對外暴露 session 的概念,session 提供一系列網絡層方法注入的實現,因為本文不是源碼解析文檔,在這里不過多論述。讀者可以簡單的認為 dubbo-go 維護了一個 getty session池,session 又維護了一個 TCP 連接池。對于每個連接,getty 會有讀協程和寫協程伴生,做到讀寫分離。這里我盡量用通俗的注釋幫大家梳理下對性能影響較大的幾個配置含義:

protocol_conf:# 這里是協議獨立的配置,在dubbo協議下,大多數配置即為getty session相關的配置。dubbo:# 一個session會始終保證connection_number個tcp連接個數,默認是16,# 但這里建議大家配置相對小的值,一般系統不需要如此多的連接個數。# 每隔reconnect_interval時間,檢查連接個數,如果小于connection_number,# 就建立連接。填0或不填都為默認值300msreconnect_interval: 0connection_number: 2# 客戶端發送心跳的間隔heartbeat_period: "30s"# OnCron時session的超時時間,超過session_timeout無返回就關閉sessionsession_timeout: "30s"# 每一個dubbo interface的客戶端,會維護一個最大值為pool_size大小的session池。# 每次請求從session池中select一個。所以真實的tcp數量是session數量*connection_number,# 而pool_size是session數量的最大值。測試總結下來一般程序4個tcp連接足以。pool_size: 4# session保活超時時間,也就是超過session_timeout時間沒有使用該session,就會關閉該sessionpool_ttl: 600# 處理返回值的協程池大小gr_pool_size: 1200# 讀數據和協程池中的緩沖隊列長度,目前已經廢棄。不使用緩沖隊列queue_len: 64queue_number: 60getty_session_param:compress_encoding: falsetcp_no_delay: truetcp_keep_alive: truekeep_alive_period: "120s"tcp_r_buf_size: 262144tcp_w_buf_size: 65536pkg_wq_size: 512tcp_read_timeout: "1s" # 每次讀包的超時時間tcp_write_timeout: "5s" # 每次寫包的超時時間wait_timeout: "1s" max_msg_len: 102400 # 最大數據傳輸長度session_name: "client"

dubbo-go 快速接入

前文已經展示過 dubbo-go 在涂鴉智能的實踐成果,接下來介紹快速接入 dubbo-go 的方式。

第一步:hello world

dubbo-go 使用范例目前和 dubbo 一致,放置在 apache/dubbo-samples 項目中。在 dubbo-sample/golang 目錄下,用戶可以選擇自己感興趣的 feature 目錄,快速測試代碼效果。

tree dubbo-samples/golang -L 1 dubbo-samples/golang ├── README.md ├── async ├── ci.sh ├── configcenter ├── direct ├── filter ├── general ├── generic ├── go.mod ├── go.sum ├── helloworld ├── multi_registry └── registry

我們以 hello world 為例,按照 dubbo-samples/golang/README.md 中的步驟,分別啟動 server 和 client 。可以嘗試 golang 調用 java 、 java 調用 golang 、golang 調用 golang 、java 調用 java。dubbo-go 在協議上支持和 dubbo 互通。

我們以啟動 go-server 為例,注冊中心默認使用 zookeeper 。首先確認本地的 zookeeper 是否運行正常。然后執行以下命令,緊接著你就可以看到你的服務正常啟動的日志了。

export ARCH=mac export ENV=dev cd dubbo-samples/golang/helloworld/dubbo/go-server sh ./assembly/$ARCH/$ENV.sh cd ./target/darwin/user_info_server-2.6.0-20200608-1056-dev/ sh ./bin/load.sh start

第二步:在項目中使用 dubbo-go

上面,我們通過社區維護的測試代碼和啟動腳本將用例跑了起來。接下來,我們需要在自己的代碼中嵌入 dubbo-go 框架。很多朋友往往是在這一步遇到問題,這里我整理的一些常見問題,希望能幫到大家。

1)環境變量

目前 dubbo-go 有 3 個環境變量需要配置:

  • CONF_CONSUMER_FILE_PATH:Consumer 端配置文件路徑,使用 consumer 時必需;
  • CONF_PROVIDER_FILE_PATH:Provider 端配置文件路徑,使用 provider 時必需;
  • APP_LOG_CONF_FILE:Log 日志文件路徑,必需;
  • CONF_ROUTER_FILE_PATH:File Router 規則配置文件路徑,使用 File Router 時需要。

2)代碼注意點

  • 注入服務 : 檢查是否執行以下代碼
# 客戶端 func init() {config.SetConsumerService(userProvider) } # 服務端 func init() {config.SetProviderService(new(UserProvider)) }
  • 注入序列化描述 :檢查是否執行以下代碼
hessian.RegisterJavaEnum(Gender(MAN))hessian.RegisterJavaEnum(Gender(WOMAN))hessian.RegisterPOJO(&User{})

3)正確理解配置文件

  • references / services 下的 key ,如下面例子的 “UserProvider” 需要和服務 Reference() 返回值保持一致,此為標識改接口的 key。
references: "UserProvider":registry: "hangzhouzk"protocol : "dubbo"interface : "com.ikurento.user.UserProvider"cluster: "failover"methods :- name: "GetUser"retries: 3
  • 注冊中心如果只有一個注冊中心集群,只需配置一個。多個 IP 用逗號隔開,如下:
registries : "hangzhouzk":protocol: "zookeeper"timeout : "3s"address: "172.16.120.181:2181,172.16.120.182:2181"username: ""password: ""

4)java 和 go 的問題

go 和 java 交互的大小寫 :golang 為了適配 java 的駝峰格式,在調用 java 服務時,會自動將 method 和屬性首字母變成小寫。很多同學故意將 java 代碼寫成適配 golang 的參數定義,將首字母大寫,最后反而無法序列化匹配。

第三步:拓展功能

dubbo-go 和 dubbo 都提供了非常豐富的拓展機制。可以實現自定義模塊代替 dubbo-go 默認模塊,或者新增某些功能。比如實現 Cluster、Filter 、Router 等來適配業務的需求。這些注入方法暴露在 dubbo-go/common/extension 中,允許用戶調用及配置。

阿里巴巴編程之夏第二期正在火熱報名中!

2020 年 5 月 25 日,阿里巴巴編程之夏(Alibaba Summer of Code,以下簡稱 ASoC )第二期正式上線,項目規模再度升級,來自開源社區的 Apache Dubbo、Apache RocketMQ、Dragonfly、Nacos 等明星開源項目多達 20 個;導師陣容配置豪華,來自阿里巴巴集團的技術專家、開源社區核心成員、Apache 孵化器導師等多達 32 位;領域涉及微服務、容器、AI 等多個熱點方向,旨在聯合開源社區打造誠意滿滿、公平公正的開源實習平臺,以阿里巴巴開源技術力量為“推手”,讓中國開源社區和開發者精英受到世界范圍內的認可。

點擊了解詳情:https://developer.aliyun.com/topic/summerofcode2020

“阿里巴巴云原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦云原生流行技術趨勢、云原生大規模的落地實踐,做最懂云原生開發者的公眾號。”

總結

以上是生活随笔為你收集整理的涂鸦智能 dubbo-go 亿级流量的实践与探索的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 日本成人免费在线视频 | 国产高清一区二区三区四区 | 风韵少妇spa私密视频 | 午夜精品一二三区 | 国模福利视频 | 国产福利视频一区二区三区 | 综合在线一区 | 一级片黄色的 | 少妇高潮一区二区三区99欧美 | 国产不卡一二三 | 久草新 | 久草青青视频 | 亚洲无码精品在线播放 | 中国女人一级片 | 成人综合色站 | 日韩av综合网 | 一区二区三区精 | 成人羞羞网站 | 三上悠亚在线观看一区二区 | 亚洲黄色免费电影 | 在线黄色大片 | 男生操女生动漫 | 国产自偷自拍视频 | 中文字幕人妻一区二区三区 | 日本高清xxxx | 黑人一区二区三区 | 日韩精品综合 | 久久尹人 | 30一40一50老女人毛片 | 久久影视一区二区 | 欧美做爰爽爽爽爽爽爽 | 无码成人精品区一级毛片 | 国产素人在线观看 | 欧美成人精品欧美一级私黄 | av免费在线观看网站 | 成人精品二区 | 亚洲中文字幕视频一区 | 日本少妇激情视频 | 欧美成人三级精品 | 日韩中文字幕在线不卡 | 日本一二三区在线视频 | 日本黄色一级视频 | 免费av黄色 | 日韩一区二区三区视频在线观看 | 大帝av| 精品无码av一区二区三区不卡 | 色中色av | 涩涩资源站 | 可以直接看的毛片 | 激情小说在线 | 精品人妻无码一区 | 美女脱了裤子让男人桶 | 国产一区精品在线观看 | 国产做爰全过程免费视频 | av手机免费在线观看 | 爱情岛论坛自拍亚洲品质极速最新章 | 日本视频免费在线播放 | 精品欧美一区二区三区 | 成年人看的免费视频 | 激情文学欧美 | 91精品国产91久久久久福利 | 99久久久久久久久久 | 毛片看 | 日韩av免费一区 | 欧美一区二区三区啪啪 | 国产伦精品视频一区二区三区 | 麻豆疯狂做受xxxx高潮视频 | 看毛片看毛片 | 亚洲熟女综合一区二区三区 | 久久精品爱 | 国产一线二线三线女 | 亚洲欧美一区二区激情 | 超碰成人97 | 性生交大片免费看l | 福利在线一区二区 | 欧美成人一区二区三区片免费 | 亚洲av综合色区无码一区 | 免费在线视频一区二区 | 精品无码av一区二区三区四区 | 男女互操视频 | 日本一区二区三区四区视频 | 国产一区二区三区四区五区美女 | 狠狠撸狠狠干 | 老女人一毛片 | 欧美群妇大交群 | 黄色三级视频在线观看 | 国产女主播福利 | 一级片免费观看视频 | 激情综合图 | 中文字幕一区二区人妻视频 | 亚洲综合无码一区二区 | 亚洲自拍偷拍av | 日日夜夜噜 | 免费无码不卡视频在线观看 | 91精品视频免费 | 国产91在线观看 | 国产高清免费 | 在线成人av | 亚洲午夜伦理 |