A. Kratos疾速入门

官网文档中写的比拟好,倡议大略浏览一遍,点击此处查看文档,重点“疾速开始.目录构造”、“疾速开始.创立我的项目”、“框架组件”里的内容

1. 装置

命令: go get -u github.com/go-kratos/kratos/cmd/kratos/v2@latest

2. 目录构造与DDD的对应关系

这个十分重要,能够从DDD层面下来了解框架的设计和整顿咱们写代码的思路

B. 开始写我的项目吧!

1. 初始化我的项目

创立我的项目

命令: kratos new 你的我的项目

我的项目编译和运行

命令行运行形式

cd 你的我的项目make allkratos run

Golang运行形式(举荐,反对断点调试)

PB文件有更新时需在编译前运行命令如下

命令: make all

GoBuild配置

RunKind: Package
PackagePath:你的我的项目/cmd/你的我的项目
WorkingDirectory: “你的我的项目”的绝对路径
Go Tool arguments: -o “你的我的项目”的绝对路径/bin/server -ldflags "-X main.Version=程序版本-X main.Name=服务名"

main.Version和main.Name 在Kratos程序外部中会应用

Program arguments: --conf 你的配置文件绝对路径


2. 定义API Protocolbuffers

新建PB文件

cd 你的我的项目
kratos proto add api/问题域/版本/畛域对象.proto
名称解析
问题域:
指的是你要解决的这个服务下某一个子问题形象的名称(倡议子问题不要太细)
版本:
API的版本,通常为v1、v2、v3
畛域对象:
就是你在这个子问题下给出的解法的形象,个别能够是性能名或者子问题域的外围对象名,依据理论状况而定
举个例子:
问题域为“元数据处理”,形象名为 metadata
版本定为v1
解决子问题为“提供环境数据管理”,形象名为 environment
最终成果为 api/metadata/v1/environment.proto

定义PB文件

初始化PB文件示例
生成的PB文件会有根本的curd的,示例如下
syntax = "proto3";

package api.metadata.v1;

option go_package = "test/api/metadata/v1;v1";
option java_multiple_files = true;
option java_package = "api.metadata.v1";

service Environment {

    rpc CreateEnvironment (CreateEnvironmentRequest) returns (CreateEnvironmentReply);    rpc UpdateEnvironment (UpdateEnvironmentRequest) returns (UpdateEnvironmentReply);    rpc DeleteEnvironment (DeleteEnvironmentRequest) returns (DeleteEnvironmentReply);    rpc GetEnvironment (GetEnvironmentRequest) returns (GetEnvironmentReply);    rpc ListEnvironment (ListEnvironmentRequest) returns (ListEnvironmentReply);

}

message CreateEnvironmentRequest {}
message CreateEnvironmentReply {}

message UpdateEnvironmentRequest {}
message UpdateEnvironmentReply {}

message DeleteEnvironmentRequest {}
message DeleteEnvironmentReply {}

message GetEnvironmentRequest {}
message GetEnvironmentReply {}

message ListEnvironmentRequest {}
message ListEnvironmentReply {}

增加HTTP反对

初始化文件中仅反对rpc调用,要增加HTTP能够在 service 里具体某个办法中增加以下option
option (google.api.http) = {

$HTTPMethod: "$URL"

};
举个例子
Get办法为
option (google.api.http) = {

get: "/api/v1/environment"

};
Post办法为
option (google.api.http) = {

post: "/api/v1/environment"body: "*" # post 办法必须要的body

};
Put办法
option (google.api.http) = {

put: "/api/v1/environment/{id}"body: "*"

};
Delete办法
option (google.api.http) = {

delete: "/api/v1/environment/{id}"

};

对于message的定义

在message能够定义你的申请参数体和返回体,更多的设置语法能够看这里, 简略示例如下
message UpdateEnvironmentRequest {
int32 id = 1 [(validate.rules).int32 = {gt:0}];
string name = 2 [(validate.rules).string.min_len = 1];
string cnName = 3;
int32 product_id = 4;
string region_name = 5;
}

message UpdateEnvironmentReply {
int32 code = 1;
string message = 2;
}

对于参数验证

在应用 validate 之前首先须要装置 proto-gen-validate
go get -d github.com/envoyproxy/protoc-gen-validate
须要在pb文件头部导入 validate.proto 文件,既import "validate/validate.proto";

具体验证语法,可查看此处,或查看kratos官网的参数校验文档

生成API代码&文档
在你的我的项目的根目录下运行命令
make api
运行完后会发现原先定义的文档里新增了Go文件以及SwaggerJson文件,对应的是代码以及文档文件

3. 编写Service

依据pb生成Service代码

运行命令,即可生成代码
kratos proto server PB文件 -t internal/service
生成代码后,即可在internal/service中编写你的逻辑
service个别仅编写 DTO 和 DO转换逻辑代码,不会波及到业务逻辑代码

注册Service

Kratos新增一个Service注册,会比拟繁琐需注意流程

internal/service 注册服务

编写完Service之后,须要在internal/service/service.go中注册服务New办法
这里kratos使用wire作为依赖注入
示例如下
package service

import (

"github.com/google/wire"

)

// ProviderSet is service providers.
var ProviderSet = wire.NewSet(

  NewEnvironmentService,

)

server/http、 server/grpc 注册服务

更改 server/http 的 NewHTTPServer办法 退出你的服务类对象,grpc同理
示例如下
func NewHTTPServer(c conf.Server, environment metadataSrv.EnvironmentService, logger log.Logger) *http.Server {

......// 必须退出以下代码实现注册metdataV1.RegisterEnvironmentHTTPServer(srv, environment)

}

4. 编写Biz

定义DO

依据你本身解决的子问题畛域形象,设计字段
留神DO定义不代表PO,DO次要围绕如何实现业务逻辑去思考,也就更多是操作、实体与实体、实体与值对象的关系梳理,对于数据的存储并不在这里思考
示例
type Environment struct {

ID        int32Name      stringCnName    stringSignature stringProduct   *ProductRegion    *RegionCreatedAt int64UpdatedAt int64

}

定义Repository接口

Repository次要负责长久化数据存储、读取等问题,因DO在这样的设计上,对应到底层的PO可能是1对N的关系,为了让这些对下层解耦,形象出Repository层来治理长久化数据的生命周期

形象成接口是为了与治理长久化数据的实现解耦,因为长久化数据的存储引擎有能够是mysql、mongodb,而加了这层之后下层就毋庸关怀了

接口在biz定义的思考在于上层变动不应该影响下层,所以该定义由下层决定,上层实现,有利于屏蔽该影响。

当然就能够了解成“下层仅需晓得本人要什么,但不须要晓得怎么来”
示例
type EnvironmentRepo interface {

CreateEnvironment(ctx context.Context, product *Environment) errorUpdateEnvironment(ctx context.Context, id int32, product *Environment) errorDeleteEnvironment(ctx context.Context, id int32) errorGetEnvironment(ctx context.Context, id int32) (*Environment, error)ListEnvironment(ctx context.Context, page, pageSize int32, names []string, productNames []string) ([]*Environment, int32, error)

}

编写业务逻辑

这里采纳了贫血模型,对于面向过程的GO语言实现来说极其敌对
申明UseCase来实现逻辑,示例
type EnvironmentUseCase struct {

repo EnvironmentRepolog  *log.Helper

}
在此UseCase绑定办法实现业务逻辑代码即可,逻辑实现重视组装业务流程,数据处理,实现业务指标

注册UseCase

编写完一个UseCase后,须要在biz/biz.go中退出该UseCase的New办法,实现注册
示例
package biz

import (

"github.com/google/wire"

)

// ProviderSet is biz providers.
var ProviderSet = wire.NewSet(

NewEnvironmentUseCase,

}

5. 编写Data

定义PO

这里须要留神你本身抉择的ORM,以后我应用的是EntORM,出至Facebook,采纳定义生成动态代码的模式提供ORM性能,性能不黑盒,容易调试,临时比照GORM的反射实现的黑盒运行,更喜爱Ent的通明,这里抉择因人而异,最好贴近团队抉择。

Ent定义生成代码

装置Ent

go get entgo.io/ent/cmd/ent

生成Schema文件

在data目录下执行以下命令
go run entgo.io/ent/cmd/ent init PO名

更改Schema文件定义字段

减少字段:在 FIelds 办法中 退出字段即可, 示例如下

func (Environment) Fields() []ent.Field {

return []ent.Field{    field.String("name").NotEmpty(),    field.String("cn_name").Default(""),    field.String("signature").NotEmpty().Unique(),    field.Int64("created_at").DefaultFunc(func() int64 { return time.Now().Unix() }).Immutable(),    field.Int64("updated_at").DefaultFunc(func() int64 { return time.Now().Unix() }).UpdateDefault(func() int64 { return time.Now().Unix() }),}

}

减少实体关系:在 Edges 办法中退出定义即可,这里波及多对多,1对1,1对多的关系定义,能够查看这里,示例如下

func (Environment) Edges() []ent.Edge {

return []ent.Edge{    edge.To("product", Product.Type).Unique(),    edge.To("region", Region.Type).Unique(),}

}
// 这里演示的是 一个environment只跟一个 product有关系, 一个environment只跟一个region有关系,

生成动态代码

在data目录中运行命令
ent generate ./ent/schema

Data类中治理ORMClient

更改data/data.go文件,依据本身所应用的缓存库、数据库库,更改Data构造体字段以及在NewData办法减少它们的初始化逻辑
比方示例如下,我应用Ent、localCache
// Data .
type Data struct {

// TODO wrapped database clientdb    *ent.Clientcache *cache.Cache

}

// NewData .
func NewData(c conf.Data, logger log.Logger) (Data, func(), error) {

logHelper := log.NewHelper(logger)client, err := ent.Open(    conf.Database.Driver,    conf.Database.Source,)// Run the auto migration tool.if err := client.Schema.Create(context.Background()); err != nil {    logHelper.Errorf("failed creating schema resources: %v", err)    return nil, nil, err}var d = &Data{    db:    client,    cache: cache.New(c.Cache.Expiration.AsDuration(), c.Cache.CleanupInterval.AsDuration()),}return d, func() {    logHelper.Info("message", "closing the data resources")    if err := d.db.Close(); err != nil {        logHelper.Error(err)    }}, nil

}

根据biz定义的Repo实现逻辑

定义实现类,示例如下
type environmentRepo struct {

data *Datalog  *log.Helper

}
实现Repository逻辑
接下来只须要实现BIZ定义的Repository接口即可

注册Repository

编写完一个Repo后,须要在data/data.go中退出该Repository的New办法,实现注册
示例
var ProviderSet = wire.NewSet(

NewData,NewEnvironmentRepo,

)

// NewData不能变,是Repo根底依赖库

6. 更新配置

批改配置

kratos对立采纳了pb治理conf,所以仅需在internal/conf/conf.proto批改配置字段即可

更新配置代码

在你的我的项目根目录下运行以下命令,更新配置代码
make config

7. Reference

https://go-kratos.dev
https://github.com/envoyproxy...
https://developers.google.com...
https://developers.google.com...
https://colobu.com/2017/03/16...
https://entgo.io/zh/docs/gett...