Kratos 学习笔记 - 命令行工具的使用方式

1,749 阅读2分钟

Kratos 一套轻量级 Go 微服务框架,包含大量微服务相关框架及工具。

名字来源于:《战神》游戏以希腊神话为背景,讲述由凡人成为战神的奎托斯(Kratos)成为战神并展开弑神屠杀的冒险历程。

工具集

kratos

kratos 命令行工具主要命令有

  • new (通过 layout 模板创建项目)
  • proto (proto 命令用于通过 proto 定义生成代码)
  • upgrade (升级 kratos 和其他配套的命令行工具)

proto-gen-go-http

proto-gen-go-http 命令行工具是用于通过 proto 定义生成 http 代码

service BlogService {
    rpc CreateArticle (CreateArticleRequest) returns (CreateArticleReply) {
        option (google.api.http) = {
            post: "/v1/article/"
            body: "*"
        };
    }
    rpc UpdateArticle (UpdateArticleRequest) returns (UpdateArticleReply) {
        option (google.api.http) = {
            put: "/v1/article/{id}"
            body: "*"
        };
    }
    rpc DeleteArticle (DeleteArticleRequest) returns (DeleteArticleReply) {
        option (google.api.http) = {
            delete: "/v1/article/{id}"
        };
    }
    rpc GetArticle (GetArticleRequest) returns (GetArticleReply) {
        option (google.api.http) = {
            get: "/v1/article/{id}"
        };
    }
}

proto-gen-go-errors

proto-gen-go-errors 命令行工具用于通过 proto 定义生成 errors 代码

enum ErrorReason {
  option (errors.default_code) = 500;
  USER_NOT_FOUND = 0 [(errors.code) = 500];
  CONTENT_MISSING = 1 [(errors.code) = 400];
}

proto-gen-validate

proto-gen-go-errors 命令行工具用于通过 proto 定义生成 validate 代码

message Request {
    int64 id = 1 [(validate.rules).int64 = {gt: 0}];
    int32 age = 2 [(validate.rules).int32 = {gt:0, lt: 120}];
    uint32 code = 3 [(validate.rules).uint32 = {in: [1,2,3]}];
    float score = 4 [(validate.rules).float = {not_in: [0, 99.99]}];
    bool state = 5 [(validate.rules).bool.const = true];
    string path = 6 [(validate.rules).string.const = "/hello"];
    string phone = 7 [(validate.rules).string.len = 11];
    string explain = 8 [(validate.rules).string.min_len = 3];
    string name = 9 [(validate.rules).string = {min_len: 1, max_len: 10}];
    string card = 10 [(validate.rules).string.pattern = "(?i)^[0-9a-f]+$"];
    Info info = 11 [(validate.rules).message.required = true];
}

Makefile

Makefile 与 kratos 命令行工具,功能基本相同,更易于用户自行定制(本文中提到的 Makefile 相关命令均以下面的代码为准,与 layout 中不同,请注意辨别)

GOPATH:=$(shell go env GOPATH)
VERSION=$(shell git describe --tags --always)
INTERNAL_PROTO_FILES=$(shell find internal -name *.proto)
API_PROTO_FILES=$(shell find api -name *.proto)
KRATOS_VERSION=$(shell go mod graph |grep go-kratos/kratos/v2 |head -n 1 |awk -F '@' '{print $$2}')
KRATOS=$(GOPATH)/pkg/mod/github.com/go-kratos/kratos/v2@$(KRATOS_VERSION)

.PHONY: init
# init env
init:
	go get -u github.com/go-kratos/kratos/cmd/kratos/v2
	go get -u google.golang.org/protobuf/cmd/protoc-gen-go
	go get -u google.golang.org/grpc/cmd/protoc-gen-go-grpc
	go get -u github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2
	go get -u github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2
	go get -u github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2
	go get -u github.com/google/wire/cmd/wire
	go get -u github.com/envoyproxy/protoc-gen-validate

.PHONY: grpc
# generate grpc code
grpc:
	protoc --proto_path=. \
		--proto_path=./third_party \
		--go_out=paths=source_relative:. \
		--go-grpc_out=paths=source_relative:. \
		$(API_PROTO_FILES)

.PHONY: http
# generate http code
http:
	protoc --proto_path=. \
		--proto_path=./third_party \
		--go_out=paths=source_relative:. \
		--go-http_out=paths=source_relative:. \
		$(API_PROTO_FILES)

.PHONY: errors
# generate errors code
errors:
	protoc --proto_path=. \
           --proto_path=./third_party \
           --go_out=paths=source_relative:. \
           --go-errors_out=paths=source_relative:. \
           $(API_PROTO_FILES)

.PHONY: validate
# generate validate code
validate:
	protoc --proto_path=. \
           --proto_path=./third_party \
           --go_out=paths=source_relative:. \
           --validate_out=paths=source_relative,lang=go:. \
           $(API_PROTO_FILES)

.PHONY: proto
# generate internal proto
proto:
	protoc --proto_path=. \
		--proto_path=./third_party \
 		--go_out=paths=source_relative:. \
		$(INTERNAL_PROTO_FILES)

.PHONY: api
# generate api proto
api:
	protoc --proto_path=. \
		--proto_path=./third_party \
 		--go_out=paths=source_relative:. \
		$(API_PROTO_FILES)

.PHONY: swagger
# generate swagger file
swagger:
	protoc --proto_path=. \
		--proto_path=./third_party \
		--openapiv2_out . \
		--openapiv2_opt logtostderr=true \
		--openapiv2_opt json_names_for_fields=false \
		$(API_PROTO_FILES)

.PHONY: generate
# generate client code
generate:
	go generate ./...

.PHONY: build
# build
build:
	mkdir -p bin/ && go build -ldflags "-X main.Version=$(VERSION)" -o ./bin/ ./...

.PHONY: test
# test
test:
	go test -v -cover ./...

.PHONY: all
# generate all
all:
	make generate;
	make grpc;
	make http;
	make errors;
	make validate;
	make proto;
	make api;
	make swagger;
	make build;
	make test;


# show help
help:
	@echo ''
	@echo 'Usage:'
	@echo ' make [target]'
	@echo ''
	@echo 'Targets:'
	@awk '/^[a-zA-Z\-\_0-9]+:/ { \
	helpMessage = match(lastLine, /^# (.*)/); \
		if (helpMessage) { \
			helpCommand = substr($$1, 0, index($$1, ":")-1); \
			helpMessage = substr(lastLine, RSTART + 2, RLENGTH); \
			printf "\033[36m%-22s\033[0m %s\n", helpCommand,helpMessage; \
		} \
	} \
	{ lastLine = $$0 }' $(MAKEFILE_LIST)

.DEFAULT_GOAL := help

安装步骤

安装 kratos 命令行工具

# 使用 go get
go get -u github.com/go-kratos/kratos/cmd/kratos/v2@latest
# 使用 go install, go 1.16版本后需要加上版本号 @latest 或者指定版本
go install github.com/go-kratos/kratos/cmd/kratos/v2

安装其他工具

通过 kratos 命令行工具的 upgrade 命令可以很方便的安装其他工具

kratos upgrade

也可以手动安装其他工具

go get -u github.com/go-kratos/kratos/cmd/kratos/v2
go get -u github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2
go get -u github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2
go get -u google.golang.org/protobuf/cmd/protoc-gen-go
go get -u google.golang.org/grpc/cmd/protoc-gen-go-grpc
go get -u github.com/envoyproxy/protoc-gen-validate
# 或者通过 go install 安装,go 1.16版本后需要加上版本号 @latest 或者指定版本
go install github.com/go-kratos/kratos/cmd/kratos/v2
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-http/v2
go install github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2
go install google.golang.org/protobuf/cmd/protoc-gen-go
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc
go install github.com/envoyproxy/protoc-gen-validate

实际使用

创建项目时指定自定义的模板仓库

kratos new hello -r https://github.com/xxx/xxx.git

创建项目时指定模板仓库的 tag 或 branch

kratos new hello -b test

构建 proto

构建 proto 时可以使用 kratos 命令行工具或者使用 Makefile

kratos 命令行工具

# kratos proto client xxxx 其中 xxx 可以为目录或指定文件,后面也可以透传参数
kratos client proto .

Makefile

make api

通过 proto 生成 http

定义 http 接口

    // 想要使用 proto 生成 http 代码的话文件中需要 import "google/api/annotations.proto";
  rpc SayHello (HelloRequest) returns (HelloReply)  {
    option (google.api.http) = {
        // 定义一个 GET 接口,并且把 name 映射到 HelloRequest
        get: "/helloworld/{name}",
        // 可以添加附加接口
        additional_bindings {
            // 定义一个 POST 接口,并且把 body 映射到 HelloRequest
            post: "/v1/greeter/say_hello",
            body: "*",
        }
    };
  }

生成代码

kratos proto client xxx.proto --go-http_opt=omitempty=false
# 或者
make http

通过 proto 生成 errors 代码

定义错误码

enum ErrorReason {
  // 设置缺省错误码
  option (errors.default_code) = 500;
  
  // 为某个枚举单独设置错误码
  USER_NOT_FOUND = 0 [(errors.code) = 404];

  CONTENT_MISSING = 1 [(errors.code) = 400];;
}

生成代码

errors 代码只会在 proto文件声明了错误码时才会生成

kratos proto client xxx.proto
# 或者
make errors

通过 proto 生成 validate 代码

定义 validate

message Request {
    int64 id = 1 [(validate.rules).int64 = {gt: 0}];
    int32 age = 2 [(validate.rules).int32 = {gt:0, lt: 120}];
    uint32 code = 3 [(validate.rules).uint32 = {in: [1,2,3]}];
    float score = 4 [(validate.rules).float = {not_in: [0, 99.99]}];
    bool state = 5 [(validate.rules).bool.const = true];
    string path = 6 [(validate.rules).string.const = "/hello"];
    string phone = 7 [(validate.rules).string.len = 11];
    string explain = 8 [(validate.rules).string.min_len = 3];
    string name = 9 [(validate.rules).string = {min_len: 1, max_len: 10}];
    string card = 10 [(validate.rules).string.pattern = "(?i)^[0-9a-f]+$"];
    Info info = 11 [(validate.rules).message.required = true];
}

生成代码

validate 代码只会在 proto文件声明了参数校验规则时才会生成

kratos proto client xxx.proto
# 或者
make validate

通过 proto 生成 grpc 代码

定义 grpc 方法

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

生成代码

validate 代码只会在 proto文件声明了参数校验规则时才会生成

kratos proto client xxx.proto
# 或者
make validate

通过 proto 生成 service 代码

生成代码

kratos proto server xxx.proto -t internal/service

参考文献