您好,登錄后才能下訂單哦!
這篇文章主要介紹“go微服務PolarisMesh服務端啟動流程是什么”,在日常操作中,相信很多人在go微服務PolarisMesh服務端啟動流程是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”go微服務PolarisMesh服務端啟動流程是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
polaris-server 作為PolarisMesh的控制面,該進程主要負責服務數據、配置數據、治理規則的管理以及下發至北極星SDK以及實現了xDS的客戶端。
golang 環境,需要1.17.x +
準備 vscode 或者 goland
從github中clone一份polaris-server的源碼,這里推薦從release-vx.y.z分支中選擇一個分支進行學習,以下文章將基于release-v1.12.0分支進行研究
# server啟動引導配置 bootstrap: # 全局日志 logger: ${日志scope名稱,主要支持 config/auth/store/naming/cache/xdsv3/default}: rotateOutputPath: ${日志文件位置} errorRotateOutputPath: ${專門記錄error級別的錯誤日志文件} rotationMaxSize: ${單個日志文件大小最大值, 默認 100, 單位為 mb} rotationMaxBackups: ${最大保存多少個日志文件, 默認 10} rotationMaxAge: ${單個日志文件最大保存天數, 默認 7} outputLevel: ${日志輸出級別,debug/info/warn/error} # 按順序啟動server startInOrder: open: true # 是否開啟,默認是關閉 key: sz # 全局鎖,鎖的名稱,根據鎖名稱進行互斥啟動 # 注冊為北極星服務 polaris_service: probe_address: ${北極星探測地址,用于獲取當前北極星server自身對外的IP, 默認為 ##DB_ADDR##} enable_register: ${是否允許當前北極星進程進行自注冊,即將自身的系統級服務注冊通過北極星的服務注冊能力進行注冊,默認為 true} isolated: ${注冊的實例是否需要處理隔離狀態,默認為 false} services: - name: polaris.checker # 北極星健康檢查需要的系統級服務,根據該服務下的實例,進行健康檢查任務的 hash 責任劃分 protocols: # 注冊的實例需要暴露的協議,即注冊端口號 - service-grpc # apiserver,北極星對外協議實現層 apiservers: - name: service-eureka # 北極星支持 eureka 協議的協議層插件 option: listenIP: "0.0.0.0" # tcp server 的監聽 ip listenPort: 8761 # tcp server 的監聽端口 namespace: default # 設置 eureka 服務默認歸屬的北極星命名空間 refreshInterval: 10 # 定期從北極星的cache模塊中拉取數據,刷新 eureka 協議中的數據緩存 deltaExpireInterval: 60 # 增量緩存過期周期 unhealthyExpireInterval: 180 # 不健康實例過期周期 connLimit: # 鏈接限制配置 openConnLimit: false # 是否開啟鏈接限制功能,默認 false maxConnPerHost: 1024 # 每個IP最多的連接數 maxConnLimit: 10240 # 當前listener最大的連接數限制 whiteList: 127.0.0.1 # 該 apiserver 的白名單 IP 列表,英文逗號分隔 purgeCounterInterval: 10s # 清理鏈接行為的周期 purgeCounterExpired: 5s # 清理多久不活躍的鏈接 - name: api-http # 北極星自身 OpenAPI 協議層 option: listenIP: "0.0.0.0" # tcp server 的監聽 ip listenPort: 8090 # tcp server 的監聽端口 enablePprof: true # 是否開啟 golang 的 debug/pprof 的數據采集 enableSwagger: true # 是否開啟 swagger OpenAPI doc 文檔數據生成 api: # 設置允許開放的 api 接口類型 admin: # 運維管理 OpenAPI 接口 enable: true console: # 北極星控制臺 OpenAPI 接口 enable: true include: [default] # 需要暴露的 OpenAPI 分組 client: # 北極星客戶端相關 OpenAPI 接口 enable: true include: [discover, register, healthcheck] config: # 北極星配置中心相關 OpenAPI 接口 enable: true include: [default] - name: service-grpc # 北極星基于 gRPC 協議的客戶端通信協議層,用于注冊發現、服務治理 option: listenIP: "0.0.0.0" listenPort: 8091 enableCacheProto: true # 是否開啟 protobuf 解析緩存,對于內容一樣的protobuf減少序列化 sizeCacheProto: 128 # protobuf 緩存大小 tls: # 協議層支持 tls 的配置 certFile: "" keyFile: "" trustedCAFile: "" api: client: enable: true include: [discover, register, healthcheck] - name: config-grpc # 北極星基于 gRPC 協議的客戶端通信協議層,用于配置中心 option: listenIP: "0.0.0.0" listenPort: 8093 connLimit: openConnLimit: false maxConnPerHost: 128 maxConnLimit: 5120 api: client: enable: true - name: xds-v3 # 北極星實現的 xDSv3 協議層 option: listenIP: "0.0.0.0" listenPort: 15010 connLimit: openConnLimit: false maxConnPerHost: 128 maxConnLimit: 10240 # 核心邏輯的配置 auth: # 鑒權插件 name: defaultAuth option: # token 加密的 salt,鑒權解析 token 時需要依靠這個 salt 去解密 token 的信息 # salt 的長度需要滿足以下任意一個:len(salt) in [16, 24, 32] salt: polarismesh@2021 # 控制臺鑒權能力開關,默認開啟 consoleOpen: true # 客戶端鑒權能力開關, 默認關閉 clientOpen: false namespace: # 是否允許自動創建命名空間 autoCreate: true naming: auth: open: false # 批量控制器 batch: ${批量控制器配置,支持 register/deregister/clientRegister/clientDeregister}: open: true # 是否開啟該批量控制器 queueSize: 10240 # 暫存任務數量 waitTime: 32ms # 任務未滿單次 Batch 數量的最大等待時間,時間到直接強制發起 Batch 操作 maxBatchCount: 128 # 單次 Batch 數量 concurrency: 128 # 處于批任務的 worker 協程數量 dropExpireTask: true # 是否開啟丟棄過期任務,僅用于 register 類型的批量控制器 taskLife: 30s # 任務最大有效期,超過有效期則任務不執行,僅用于 register 類型的批量控制器 # 健康檢查的配置 healthcheck: open: true # 是否開啟健康檢查功能模塊 service: polaris.checker # 參與健康檢查任務的實例所在的服務 slotNum: 30 # 時間輪參數 minCheckInterval: 1s # 用于調整實例健康檢查任務在時間輪內的下一次執行時間,限制最小檢查周期 maxCheckInterval: 30s # 用于調整實例健康檢查任務在時間輪內的下一次執行時間,限制最大檢查周期 clientReportInterval: 120s # 用于調整SDK上報實例健康檢查任務在時間輪內的下一次執行時間 batch: # 健康檢查數據的批量寫控制器 heartbeat: open: true queueSize: 10240 waitTime: 32ms maxBatchCount: 32 concurrency: 64 checkers: # 健康檢查啟用插件列表,當前支持 heartbeatMemory/heartbeatRedis,由于二者屬于同一類型健康檢查插件,因此只能啟用一個 - name: heartbeatMemory # 基于本機內存實現的健康檢查插件,僅適用于單機版本 - name: heartbeatRedis # 基于 redis 實現的健康檢查插件,適用于單機版本以及集群版本 option: kvAddr: ##REDIS_ADDR## # redis 地址,IP:PORT 格式 # ACL user from redis v6.0, remove it if ACL is not available kvUser: ##REDIS_USER# # 如果redis版本低于6.0,請直接移除該配置項 kvPasswd: ##REDIS_PWD## # redis 密碼 poolSize: 200 # redis 鏈接池大小 minIdleConns: 30 # 最小空閑鏈接數量 idleTimeout: 120s # 認為空閑鏈接的時間 connectTimeout: 200ms # 鏈接超時時間 msgTimeout: 200ms # redis的讀寫操作超時時間 concurrency: 200 # 操作redis的worker協程數量 withTLS: false # 配置中心模塊啟動配置 config: # 是否啟動配置模塊 open: true cache: #配置文件緩存過期時間,單位s expireTimeAfterWrite: 3600 # 緩存配置 cache: open: true resources: - name: service # 加載服務數據 option: disableBusiness: false # 不加載業務服務 needMeta: true # 加載服務元數據 - name: instance # 加載實例數據 option: disableBusiness: false # 不加載業務服務實例 needMeta: true # 加載實例元數據 - name: routingConfig # 加載路由數據 - name: rateLimitConfig # 加載限流數據 - name: circuitBreakerConfig # 加載熔斷數據 - name: users # 加載用戶、用戶組數據 - name: strategyRule # 加載鑒權規則數據 - name: namespace # 加載命名空間數據 - name: client # 加載 SDK 數據 # 存儲配置 store: # 單機文件存儲插件 name: boltdbStore option: path: ./polaris.bolt ## 數據庫存儲插件 # name: defaultStore # option: # master: # 主庫配置, 如果要配置 slave 的話,就把 master 替換為 slave 即可 # dbType: mysql # 數據庫存儲類型 # dbName: polaris_server # schema 名稱 # dbUser: ##DB_USER## # 數據庫用戶 # dbPwd: ##DB_PWD## # 數據庫用戶密碼 # dbAddr: ##DB_ADDR## # 數據庫連接地址,HOST:PORT 格式 # maxOpenConns: 300 # 最大數據庫連接數 # maxIdleConns: 50 # 最大空閑數據庫連接數 # connMaxLifetime: 300 # 單位秒 # 連接的最大存活時間,超過改時間空閑連接將會唄釋放 # txIsolationLevel: 2 #LevelReadCommitted # 插件配置 plugin: # 本次暫不涉及,后續文章在詳細說明
我們先來看下,北極星服務端源碼的組織形式
? polaris-server git:(release-v1.12.0) tree -L 1 . ├── apiserver # 北極星對外協議實現層 ├── auth # 北極星的資源鑒權層 ├── bootstrap # 負責將北極星各個功能模塊初始化、逐個啟動 ├── cache # 北極星的資源緩存層,對于弱一致性讀接口進行加速 ├── cmd # 簡單實現幾個 command 命令,start:啟動北極星,version: 查詢當前北極星進程版本 ├── common # 公共模塊,放置api接口對象定義、功能模塊的工具函數 ├── config # 北極星的配置中心 ├── main.go # main 函數所在文件,polaris-server 進程啟動的入口 ├── maintain # 北極星自身運維能力模塊 ├── namespace # 北極星命名空間模塊,主要用于服務注冊發現以及配置中心 ├── plugin # 北極星小功能插件模塊,主要集中了各個旁路能力的默認插件實現 ├── plugin.go # 北極星的插件注冊文件,利用 golang 的 init 機制 ├── polaris-server.yaml # polaris-server 進程啟動所需要的配置文件 ├── service # 北極星的服務注冊發現中心、治理規則中心 ├── store # 北極星的存儲層,已插件化,存在兩個默認實現插件,一個是基于boltdb實現的單機存儲插件,一個是基于MySQL實現的集群存儲插件 ├── tool # 北極星的相關腳本,包含啟動、關閉 └── version # 編譯期間注入版本信息
從源碼的組織中可以看出,北極星各個功能模塊的劃分還是很清晰的,其核心的模塊主要是以下六個
apiserver
bootstrap
cache
namespace
config
service
我們先來看看,是如何在bootstrap中完成對北極星各個功能模塊的初始化以及逐個啟動的
先看看 bootstrap 下的源碼文件組織
? bootstrap git:(release-v1.12.0) tree -L 1 . ├── config # bootstrap 在 polaris-server.yaml 中對應的配置對象 ├── run_darwin.go # 用于 drawin 內核,阻塞 polaris-server 主協程不退出,并監聽相應的os.Signal ├── run_linux.go # 用于 linux 內核,阻塞 polaris-server 主協程不退出,并監聽相應的os.Signal ├── run_windows.go # 用于 window 內核,阻塞 polaris-server 主協程不退出,并監聽相應的os.Signal ├── self_checker.go # 北極星服務端自身的心跳上報流程,保持自身注冊的相關內置服務實例的健康 └── server.go # 北極星啟動核心邏輯文件
既然 server.go 是服務端進程啟動核心邏輯所在的文件,那我們就直接從他入手。
來到 server.go 文件中,立馬就看到一個 Start(configFilePath string) 方法,毋庸置疑,這肯定就是北極星服務端啟動的核心入口。我們來簡單看看,server.go#Start(configFilePath string) 主要做了哪些事情
func Start(configFilePath string) { // 根據所給定的配置文件路徑信息,加載對應的配置文件內容, 這里指的就是 polaris-server.yaml 中的內容 cfg, err := boot_config.Load(configFilePath) ... // 根據配置文件內容中對于日志模塊的配置, 初始化日志模塊 err = log.Configure(cfg.Bootstrap.Logger) // 初始化相關指標收集器 metrics.InitMetrics() // 設置插件配置 plugin.SetPluginConfig(&cfg.Plugin) // 初始化存儲層 store.SetStoreConfig(&cfg.Store) // 開啟進入啟動流程,初始化插件,加載數據等 var tx store.Transaction // 根據 ${bootstrap.startInOrder.key} 從存儲層獲取一把鎖,如果鎖獲取成功,則繼續執行 tx, err = StartBootstrapInOrder(s, cfg) if err != nil { // 多次嘗試加鎖失敗 fmt.Printf("[ERROR] bootstrap fail: %v\n", err) return } // 啟動北極星服務端的功能模塊(服務發現、服務治理、配置中心等等) err = StartComponents(ctx, cfg) ... // 啟動北極星的 apiserver 插件,對于 polaris-server.yaml 中配置的 apiserver 均會進行啟動 servers, err := StartServers(ctx, cfg, errCh) // 北極星服務端自注冊邏輯,方便其他節點感知到自己的存在 if err := polarisServiceRegister(&cfg.Bootstrap.PolarisService, cfg.APIServers); err != nil { fmt.Printf("[ERROR] register polaris service fail: %v\n", err) return } // 服務端啟動完成,發起請求到存儲層,釋放名為${bootstrap.startInOrder.key}的鎖 // 其他北極星節點便可以獲取到鎖之后繼續完成自己的啟動邏輯 _ = FinishBootstrapOrder(tx) fmt.Println("finish starting server") // 簡單的死循環邏輯,監聽 os.Signal 完成 apiserver 重啟、服務端優雅下線邏輯 RunMainLoop(servers, errCh) }
簡單的梳理 server.go#Start(configFilePath string) 中邏輯,主要就是做了這么幾個事情
配置文件加載識別、初始化相關功能模塊配置
從存儲層申請用于進程啟動的分布式鎖
啟動服務端功能模塊
釋放自身對于啟動分布式鎖的占用
啟動 apiserver
接著我們來看下功能模塊是如何逐個開啟的。
北極星的功能模塊主要有三個
APIServer
命名空間
服務注冊發現、服務治理
配置中心
北極星的旁路功能模塊則為
數據存儲層
資源鑒權
數據緩存
運維模塊
北極星的 APIServer 層,通過插件化的設計,將北極星的能力通過各個協議對外提供,以及對其他注冊中心組件的協議兼容。APIServer 的定義如下
type Apiserver interface { // GetProtocol API協議名 GetProtocol() string // GetPort API的監聽端口 GetPort() uint32 // Initialize API初始化邏輯 Initialize(ctx context.Context, option map[string]interface{}, api map[string]APIConfig) error // Run API服務的主邏輯循環 Run(errCh chan error) // Stop 停止API端口監聽 Stop() // Restart 重啟API Restart(option map[string]interface{}, api map[string]APIConfig, errCh chan error) error }
可以看到,APIServer interface 只是定義了 APIServer 插件的相關生命周期定義,并沒有具體限制 APIServer 改如何處理數據請求,因此使得 APIServer 相關插件實現,即可以將北極星的能力通過 gRPC、HTTP 協議對外提供,同時也可以通過 APIServer 插件對 eureka、xds 等第三方協議進行適配,將其轉換為北極星的相關能力接口以及數據模型。 當前北極星 APIServer 已有的插件列表如下
httpserver: 通過 HTTP 協議對外提供北極星服務端的 OpenAPI 以及和客戶端進行數據通信的 ClientAPI
grpcserver: 通過 gRPC 協議提供北極星和客戶端進行數據通信
eurekaserver: 通過 HTTP 協議,將 eureka 的能力適配成北極星的相關能力接口,以及將 eureka 數據模型映射為北極星的數據模型
xdsv3server: 根據 xds control plane 的協議標準,將北極星的服務模型、治理模型轉為 xds 模型,對外提供 xds 的能力,使得北極星可以對接 envoy 等相關基于 xds 實現的數據面
// StartComponents start health check and naming components func StartComponents(ctx context.Context, cfg *boot_config.Config) error { var err error ... // 初始化緩存模塊 if err := cache.Initialize(ctx, &cfg.Cache, s); err != nil { return err } }
緩存層模塊初始化的觸發在 StartComponents 流程中,在初始化過程中,會根據 polaris-server.yaml 配置文件中關于 cache 配置的 resources 列表,按需啟動相關資源的 cache 實現
// 構建 CacheManager 對象實例,并構造所有資源的 Cache 接口實現實例 func newCacheManager(_ context.Context, cacheOpt *Config, storage store.Store) (*CacheManager, error) { SetCacheConfig(cacheOpt) mgr := &CacheManager{ storage: storage, caches: make([]Cache, CacheLast), comRevisionCh: make(chan *revisionNotify, RevisionChanCount), revisions: map[string]string{}, } // 構建服務實例緩存 cache ic := newInstanceCache(storage, mgr.comRevisionCh) // 構建服務緩存 cache sc := newServiceCache(storage, mgr.comRevisionCh, ic) mgr.caches[CacheService] = sc mgr.caches[CacheInstance] = ic // 構建路由規則緩存 cache mgr.caches[CacheRoutingConfig] = newRoutingConfigCache(storage, sc) // 構建限流規則緩存 cache mgr.caches[CacheRateLimit] = newRateLimitCache(storage) // 構建熔斷規則緩存 cache mgr.caches[CacheCircuitBreaker] = newCircuitBreakerCache(storage) notify := make(chan interface{}, 8) // 構建用戶列表緩存 cache mgr.caches[CacheUser] = newUserCache(storage, notify) // 構建鑒權策略緩存 cache mgr.caches[CacheAuthStrategy] = newStrategyCache(storage, notify, mgr.caches[CacheUser].(UserCache)) // 構建命名空間緩存 cache mgr.caches[CacheNamespace] = newNamespaceCache(storage) // 構建SDK實例信息緩存 cache mgr.caches[CacheClient] = newClientCache(storage) if len(mgr.caches) != CacheLast { return nil, errors.New("some Cache implement not loaded into CacheManager") } ... // 根據 polaris-server.yaml 配置完成最終的緩存模塊啟動 if err := mgr.initialize(); err != nil { return nil, err } return mgr, nil } // initialize 緩存對象初始化 func (nc *CacheManager) initialize() error { for _, obj := range nc.caches { var option map[string]interface{} // 根據配置文件中的 resource 列表,按需啟動相關的 cache for _, entry := range config.Resources { if obj.name() == entry.Name { option = entry.Option break } } if err := obj.initialize(option); err != nil { return err } } return nil }
// StartComponents start health check and naming components func StartComponents(ctx context.Context, cfg *boot_config.Config) error { ... cacheMgn, err := cache.GetCacheManager() if err != nil { return err } // 初始化鑒權層 if err = auth.Initialize(ctx, &cfg.Auth, s, cacheMgn); err != nil { return err } }
資源鑒權模塊初始化的觸發在 StartComponents 流程中,由于資源鑒權模塊主要任務是根據配置的鑒權規則,針對每次請求都進行一次策略計算,因此為了節省查詢相關規則的時間,以及鑒權規則信息、用戶信息變化不頻繁的假定之下,資源鑒權模塊默認從資源緩存模塊中獲取相關對象,執行計算并返回最終的資源鑒權結果。
// StartComponents start health check and naming components func StartComponents(ctx context.Context, cfg *boot_config.Config) error { ... // 初始化命名空間模塊 if err := namespace.Initialize(ctx, &cfg.Namespace, s, cacheMgn); err != nil { return err } }
命名空間模塊初始化的觸發在 StartComponents 流程中,polaris 的服務注冊發現、配置中心的模型設計中都依賴命名空間,因此將命名空間相關能力獨立出來。 命名空間模塊相關的數據操作不是非常頻繁,數據操作都是直接和數據存儲層進行交互,而依賴緩存模塊則是為了解決在創建服務、配置時觸發的命名空間自動創建動作,為了減少對數據存儲層的調用,通過緩存存在性判斷以及 singleflight.Group 組件來實現。
// StartComponents start health check and naming components func StartComponents(ctx context.Context, cfg *boot_config.Config) error { ... // 初始化服務發現模塊相關功能 if err := StartDiscoverComponents(ctx, cfg, s, cacheMgn, authMgn); err != nil { return err } }
服務注冊發現、服務治理模塊初始化的觸發在 StartComponents 流程中的 StartDiscoverComponents 方法。StartDiscoverComponents 具體做的事情如下
創建注冊、反注冊批量控制器
為了提高服務端注冊、反注冊的TPS,這里做了一個數據寫操作的Batch優化,盡可能將一段時間內一定量的數據寫操作合并成一個大的數據寫操作發往數據存儲層,減少對于數據存儲層的調用次數以及帶來的額外網絡開銷,提升整體服務端的請求吞吐量
創建服務實例健康檢查組件
對于服務實例的健康狀態檢查,有專門的 HealthCheckerServer 進行處理,該模塊會監聽緩存模塊中的InstanceCache的數據變化事件,從中選擇開啟了健康檢查的實例,將其納入健康檢查任務的TimeWheel中進行周期性調度檢查
實例的健康檢查機制,當前 polaris 服務端做了插件化設計,默認 HealthCheck 插件實現為檢查實例的心跳上報周期,該實現有兩種具體的實現方式,針對單機模式來說具體實現為 heartbeatMemory,即實例的心跳數據存儲在服務端內部中;針對集群模式來說具體實現為 heartbeatRedis,即實例的心跳數據存儲在 redis 集群中,從而各個服務端節點都可以獲取到任意實例的上次心跳上報時間。
創建 naming.Service 接口實例,完成服務注冊發現、服務治理模塊的初始化
創建帶 auth 能力的 naming.Service 接口實例,注入資源權限檢查能力。
// StartComponents start health check and naming components func StartComponents(ctx context.Context, cfg *boot_config.Config) error { ... // 初始化配置中心模塊相關功能 if err := StartConfigCenterComponents(ctx, cfg, s, cacheMgn, authMgn); err != nil { return err } }
配置中心模塊初始化的觸發在 StartComponents 流程中的 StartConfigCenterComponents 方法。StartConfigCenterComponents 具體做的事情如下
創建配置文件緩存組件,加速客戶端讀取配置文件,減少和存儲層的交互次數
創建 Watch 客戶端鏈接管理組件,管理每條鏈接上感興趣的配置文件列表。
創建配置發布事件中心,通過配置發布事件以及 Watch 客戶端連接管理組件,將相關配置變更事件通知給相關的客戶端,實現配置監聽能力
到此,關于“go微服務PolarisMesh服務端啟動流程是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。