Kratos漫游指南 1 - 概覽


您好,地球人,歡迎來到Kratos漫游指南。

對於剛開始研究Kratos框架的開發者來說,目前的文檔有些零散,這與我們的模塊化設計有一些關系,不過Don't panic,從這篇文章開始,我將試圖打破這一現狀,漫游指南系列將循序漸進地介紹Kratos框架,理順框架的使用思路,使您更快上手Kratos。

同時,這個系列也會逐步整合進官方文檔中,同時重新組織整個文檔的結構和內容,敬請期待。

本篇是該系列的第一篇,主要介紹Kratos的整體概況。

設計哲學

Kratos是一個Go語言實現的微服務框架,說得更准確一點,它更類似於一個使用Go構建微服務的工具箱,開發者可以按照自己的習慣選用或定制其中的的組件,來打造自己的微服務。也正是由於這樣的原因,Kratos並不綁定於特定的基礎設施,不限定於某種注冊中心,或數據庫ORM等,所以您可以十分輕松地將任意庫集成進項目里,與Kratos共同運作。

圍繞這樣的核心設計理念,我們設計了如下的項目生態:

  • kratos Kratos框架核心,主要包含了基礎的CLI工具,內置的HTTP/gRPC接口生成和服務生命周期管理,提供鏈路追蹤、配置文件、日志、服務發現、監控等組件能力和相關接口定義。
  • contrib 基於上述核心定義的基礎接口,對配置文件、日志、服務發現、監控等服務進行具體實現所形成的一系列插件,可以直接使用它們,也可以參考它們的代碼,做您需要的服務的適配,從而集成進kratos項目中來。
  • aegis 我們將服務可用性相關的算法:如限流、熔斷等算法放在了這個獨立的項目里,幾乎沒有外部依賴,它更不依賴Kratos,您可以在直接在任意項目中使用。您也可以輕松將它集成到Kratos中使用,提高服務的可用性。
  • layout 我們設計的一個默認的項目模板,它包含一個參考了DDD和簡潔架構設計的項目結構、Makefile腳本和Dockerfile文件。但這個項目模板不是必需的,您可以任意修改它,或使用自己設計的項目結構,Kratos依然可以正常工作。框架本身不對項目結構做任何假設和限制,您可以按照自己的想法來使用,具有很強的可定制性。
  • gateway 這個是我們剛剛起步,用Go開發的API Gateway,后續您可以使用它來作為您Kratos微服務的網關,用於微服務API的治理,項目正在施工中,歡迎關注。

倉庫、文檔和社區

GitHub倉庫:https://github.com/go-kratos
文檔:https://go-kratos.dev/
微信群:go-kratos 官方微信群
Discord:go-kratos

為什么v2完全重新設計

以前關注過kratos項目的可能知道,Kratos的v1版本已經開源了很久,也是個較為完善的框架。那么為什么不直接基於v1繼續迭代,而是要推倒重來,推出完全重新設計的v2呢?

經驗源自踩坑。

在業務不斷迭代、項目不斷膨脹的情況下,我們發現,過去的框架和項目結構設計,導致代碼變更成本逐漸升高,而沒有進行合理的抽象,導致更難進行模塊的測試,也更難對第三方基礎庫進行適配和遷移,這在一定程度上拉低了生產力。

因此,我們參考了大量的DDD和Clean Architecture等業界先進設計理念,重新設計了微服務的項目結構,並且這個結構隨着我們的后續研究,會進一步進行迭代,讓它成為微服務項目結構的最佳實踐。

沒錯,新版本的是從kratos-layout開始的。也許剛接觸這個項目結構時會覺得不適應,但隨着項目迭代,代碼復雜度的提高,這個定義良好的結構,將使項目保持優秀的代碼可讀性、可測試性,以及令人滿意的開發效率和可維護性。

更重要的一點是,這一次我們想面向社區來設計和開發這個框架。讓更多的開發者能夠使用我們的框架來提高生產力,同時參與到我們的項目中來。

所以我們把整個框架設計成為一個插座,我們希望整個框架輕量,插件化,可定制。對於幾乎每一個微服務相關的功能模塊,我們都設計了標准化接口,對於第三方庫設計為插件,這樣就能迅速把任意基礎設施集成到使用Kratos的項目里,因此,無論您的公司使用何種基礎設施,有何種規范,您都可以輕松將Kratos定制成與您的開發、生產環境相匹配的樣子。

不破不立,v2是一次從內到外的徹底革新,我們無法在舊版本上修修補補,而是選擇重新設計和開發新版本。而目前v2版本也已經在很多生產環境使用,我們也將持續迭代和完善這個框架,同時也更歡迎各位開發者參與進來,一起讓它變得更好。

數據庫/緩存/消息隊列/...

正如前文提到的,Kratos框架不限制您使用任何第三方庫來進行項目開發,因此您可以根據喜好來選擇庫進行集成。我們也會逐步針對更多被廣泛使用的第三方庫開發插件。

這里給出一些被廣泛使用的庫供參考:

數據庫:

緩存:

消息隊列:

其它更多的優秀go庫,可以在awesome-go這個倉庫中找找。

CLI工具

kratos命令目前主要用於從模板創建項目,維護依賴包版本等。具體請參考文檔

Protobuf定義API

Kratos使用Protobuf進行API定義。Protobuf是由Google開發的一種語言中立的數據序列化協議。它有結構定義清晰、可擴展性好、體積小、性能優秀等特點,在眾多公司和項目被廣泛使用。

在使用Kratos的項目中,您將使用如下的IDL進行您的接口定義,並且通過protoc工具生成相應的.pb.go文件,其中包含根據定義生成的的服務端和客戶端代碼。隨后您就可以在自己的項目內部注冊服務端代碼使用,或引用客戶端代碼進行遠程調用。

Kratos默認僅生成gRPC接口的代碼,如果需要生成HTTP代碼,請在proto文件中使用option (google.api.http)來添加HTTP部分的定義后再進行生成。默認情況下,HTTP接口將使用JSON作為序列化格式,如果想使用其它序列化格式(form,XML等),請參考文檔序列化進行相應的配置即可。

syntax = "proto3";

package helloworld.v1;

import "google/api/annotations.proto";

option go_package = "github.com/go-kratos/kratos-layout/api/helloworld/v1;v1";

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply)  {
        option (google.api.http) = {
            get: "/helloworld/{name}"
        };
    }
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

需要注意,雖然Protobuf定義的API的可靠性更強,但字段結構靈活性相對JSON要弱一些,因此如果您有諸如文件上傳接口,或者某些無法對應到proto的JSON結構需要使用,我門還提供了“逃生門”,在我們的Protobuf體系之外定義這些接口,實現為普通的http.Handler並且掛載到路由上,或者用struct來定義您的字段。可以參考我們的upload例子進行實現。

元信息傳遞

服務之間的API調用,如果有某些元信息需要傳遞過去,而不是寫在payload消息中,可以使用Metadata包進行字段設置和提取,具體細節參考元信息傳遞文檔

錯誤處理

Kratos的errors模塊提供了error的封裝。框架也預定義了一系列標准錯誤供使用。

錯誤處理這一塊的設計也經過了很久的討論才定下來,主要設計理念如下:

  1. code 語義近似HTTP的Status Code(例如客戶端傳參數錯誤用400)同時也作為大類錯誤,在HTTP接口中的HTTP Code會使用它,好處是網關層可以根據這個code觸發相應策略(重試、限流、熔斷等)。
  2. reason 業務的具體錯誤碼,為可讀的字符串,能夠表明,在同一個服務中應該唯一。
  3. message 用戶可讀的信息,可以在客戶端(App、瀏覽器等)進行相應的展示給用戶看。
  4. metadata 為一些附加信息,可以作為補充信息使用。

在API返回的錯誤信息中,以HTTP接口為例,消息結構大概是長這個樣子的:

{
    // 錯誤碼,跟 http-status 一致,並且在 grpc 中可以轉換成 grpc-status
    "code": 500,
    // 錯誤原因,定義為業務判定錯誤碼
    "reason": "USER_NOT_FOUND",
    // 錯誤信息,為用戶可讀的信息,可作為用戶提示內容
    "message": "invalid argument error",
    // 錯誤元信息,為錯誤添加附加可擴展信息
    "metadata": {"some-key": "some-value"}
}

在Kratos中您可以使用proto文件定義您的業務錯誤,並通過工具生成對應的處理邏輯和方法。(如使用layout中提供的make errors指令。)

錯誤定義:

syntax = "proto3";

package api.blog.v1;
import "errors/errors.proto";

option go_package = "github.com/go-kratos/kratos/examples/blog/api/v1;v1";

enum ErrorReason {
  // 設置缺省錯誤碼
  option (errors.default_code) = 500;
  
  // 為某個枚舉單獨設置錯誤碼
  USER_NOT_FOUND = 0 [(errors.code) = 404];
  CONTENT_MISSING = 1 [(errors.code) = 400];;
}

錯誤創建:

// 通過 errors.New() 響應錯誤
errors.New(500, "USER_NAME_EMPTY", "user name is empty")

// 通過 proto 生成的代碼響應錯誤,並且包名應替換為自己生成代碼后的 package name
api.ErrorUserNotFound("user %s not found", "kratos")

// 傳遞metadata
err := errors.New(500, "USER_NAME_EMPTY", "user name is empty")
err = err.WithMetadata(map[string]string{
    "foo": "bar",
})

錯誤斷言:

err := wrong()

// 通過 errors.Is() 斷言
if errors.Is(err,errors.BadRequest("USER_NAME_EMPTY","")) {
    // do something
}

// 通過判斷 *Error.Reason 和 *Error.Code
e := errors.FromError(err)
if  e.Reason == "USER_NAME_EMPTY" && e.Code == 500 {
    // do something
}

// 通過 proto 生成的代碼斷言錯誤,並且包名應替換為自己生成代碼后的 package name
if api.IsUserNotFound(err) {
        // do something
})

配置文件

Kratos提供了統一的接口,支持配置文件的加載和變更訂閱。

通過實現Source 和 Watcher即可實現任意配置源(本地或遠程)的配置文件加載和變更訂閱。

已經實現了下列插件:

服務注冊&服務發現

Kratos定義了統一的注冊接口,通過實現Registrar和Discovery,您可以很輕松地將Kratos接入到您的注冊中心中。

您也可以直接使用我們已經實現好的插件:

日志

Kratos的日志模塊由兩部分組成:

  1. Logger:底層日志接口,用於快速適配各種日志庫到框架中來,僅提供一個最簡單的Log方法。
  2. Helper:高級日志接口,提供了一系列帶有日志等級和格式化方法的幫助函數,通常業務邏輯中建議使用這個,能夠簡化日志代碼。

我們已經實現好的插件用於適配目前一些日志庫,您也可以參考它們的代碼來實現自己需要的日志庫的適配:

監控

監控告警方面,您可以通過實現metrics相關接口將服務的統計數據上報給監控平台。

也可以直接使用我們已經實現好的插件:

鏈路追蹤

Kratos使用OpenTelemetry作為分布式鏈路追蹤所使用的標准,您可以通過對client和server配置tracing來將服務接入到鏈路追蹤平台(如jaeger等),從而對服務的接口調用關系,耗時,錯誤等進行追蹤。

負載均衡

Kratos內置了若干種負載均衡算法,如Weighted round robin(默認)、P2C,Random等,您可以通過在client初始化時配置來使用他們。

限流熔斷

Kratos提供了限流ratelimit熔斷circuitbreaker中間件,用於微服務出現異常故障時自動對流量進行限制,提升服務的健壯性,避免雪崩。這兩個中間件使用的算法,也可以在我們的可用性算法倉庫aegis中找到,獨立於Kratos直接使用。

中間件

您可以通過Kratos的middleware機制,統一微服務接口的某些共同邏輯。上面提到的功能插件,您可以通過實現Middleware編寫Kratos能夠使用的中間件。

同時在倉庫的middleware目錄下,我們也提供了一系列中間件供您使用。

插件

除了上述提到的插件外,我們還提供了一些其它插件,完整的插件列表請參考文檔社區插件

示例代碼

如果您看過文檔后,對某些功能的使用仍有疑惑,或者是希望尋找一些用Kratos寫項目的靈感,在倉庫的examples目錄下我們提供了很多代碼供參考。

您也可以通過文檔中的示例代碼清單頁面來查閱有哪些示例。

小結

使用Kratos在一般開發過程中用到大部分常用功能點,在本文已經做了簡單介紹,相信您對本框架的情況已經有了大致的了解。限於篇幅原因,無法在一篇文章中涵蓋到Kratos的全部細節,比如layout這個相對復雜的項目結構具體是怎么用的,我將在后續的文章中,繼續對Kratos的框架設計思想和使用方法做更加詳細的介紹,並且會結合具體的項目實例,介紹使用Kratos開發的完整流程。

文章轉自



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM