From e39351d0d1f917bcf3401631e411f45c6a8bf2eb Mon Sep 17 00:00:00 2001 From: felixhao Date: Wed, 24 Apr 2019 00:07:47 +0800 Subject: [PATCH] add doc for warden --- doc/wiki-cn/blademaster-mid.md | 3 + doc/wiki-cn/blademaster-mod.md | 3 + doc/wiki-cn/blademaster-quickstart.md | 1 - doc/wiki-cn/blademaster.md | 3 + doc/wiki-cn/summary.md | 7 +- doc/wiki-cn/warden-balancer.md | 0 doc/wiki-cn/warden-quickstart.md | 158 ++++++++++++++++++++++++++ doc/wiki-cn/warden-resolver.md | 0 doc/wiki-cn/warden.md | 49 ++++++++ 9 files changed, 221 insertions(+), 3 deletions(-) create mode 100644 doc/wiki-cn/warden-balancer.md create mode 100644 doc/wiki-cn/warden-quickstart.md create mode 100644 doc/wiki-cn/warden-resolver.md diff --git a/doc/wiki-cn/blademaster-mid.md b/doc/wiki-cn/blademaster-mid.md index 28f36fd0c..f43949e73 100644 --- a/doc/wiki-cn/blademaster-mid.md +++ b/doc/wiki-cn/blademaster-mid.md @@ -103,6 +103,9 @@ func Example() { } ``` +# 扩展阅读 + +[bm快速开始](blademaster-quickstart.md) [bm模块说明](blademaster-mod.md) [bm基于pb生成](blademaster-pb.md) ------------- diff --git a/doc/wiki-cn/blademaster-mod.md b/doc/wiki-cn/blademaster-mod.md index 1aac31c66..8c7ac75d3 100644 --- a/doc/wiki-cn/blademaster-mod.md +++ b/doc/wiki-cn/blademaster-mod.md @@ -78,6 +78,9 @@ func (c *Context) Protobuf(data proto.Message, err error) 部分中间件可能想要在过程中中断整个流程,此时可以使用 Abort() 方法提前结束处理。 有些中间件还想在所有 Handler 执行完后再执行部分逻辑,此时可以在自身 Handler 中显式调用 Next() 方法,并将这些逻辑放在调用了 Next() 方法之后。 +# 扩展阅读 + +[bm快速开始](blademaster-quickstart.md) [bm中间件](blademaster-mid.md) [bm基于pb生成](blademaster-pb.md) ------------- diff --git a/doc/wiki-cn/blademaster-quickstart.md b/doc/wiki-cn/blademaster-quickstart.md index 0fec788b2..eca87f42d 100644 --- a/doc/wiki-cn/blademaster-quickstart.md +++ b/doc/wiki-cn/blademaster-quickstart.md @@ -63,7 +63,6 @@ func howToStart(c *bm.Context) // handler方法默认传入bm的Context对象 [bm模块说明](blademaster-mod.md) [bm中间件](blademaster-mid.md) [bm基于pb生成](blademaster-pb.md) - ------------- [文档目录树](summary.md) diff --git a/doc/wiki-cn/blademaster.md b/doc/wiki-cn/blademaster.md index 94e97ff96..21d2f2f9e 100644 --- a/doc/wiki-cn/blademaster.md +++ b/doc/wiki-cn/blademaster.md @@ -32,6 +32,9 @@ blademaster 处理请求的模式非常简单,大部分的逻辑都被封装 但是 Handler 中可以也中断整个处理流程,直接输出 Response。这种模式常被用于校验登陆的中间件中;一旦发现请求不合法,直接响应拒绝。 请求处理的流程中也可以使用 Render 来辅助渲染 Response,比如对于不同的请求需要响应不同的数据格式(JSON、XML),此时可以使用不同的 Render 来简化逻辑。 +# 扩展阅读 + +[bm快速开始](blademaster-quickstart.md) [bm模块说明](blademaster-mod.md) [bm中间件](blademaster-mid.md) [bm基于pb生成](blademaster-pb.md) ------------- diff --git a/doc/wiki-cn/summary.md b/doc/wiki-cn/summary.md index d0f604d34..67abf002f 100644 --- a/doc/wiki-cn/summary.md +++ b/doc/wiki-cn/summary.md @@ -9,8 +9,11 @@ * [bm middleware](blademaster-mid.md) * [bm protobuf](blademaster-pb.md) * [grpc warden](warden.md) - * [middleware](warden-mid.md) - * [protobuf生成](warden-pb.md) + * [warden quickstart](warden-quickstart.md) + * [warden interceptor](warden-mid.md) + * [warden resolver](warden-resolver.md) + * [warden balancer](warden-balancer.md) + * [warden protobuf](warden-pb.md) * [dapper trace](dapper.md) * [log](logger.md) * [log-agent](log-agent.md) diff --git a/doc/wiki-cn/warden-balancer.md b/doc/wiki-cn/warden-balancer.md new file mode 100644 index 000000000..e69de29bb diff --git a/doc/wiki-cn/warden-quickstart.md b/doc/wiki-cn/warden-quickstart.md new file mode 100644 index 000000000..359a2f87c --- /dev/null +++ b/doc/wiki-cn/warden-quickstart.md @@ -0,0 +1,158 @@ +# 准备工作 + +推荐使用[kratos tool](kratos-tool.md)快速生成项目,如我们生成一个叫`kratos-demo`的项目。 + +[快速开始](quickstart.md) + +# pb文件 + +创建项目成功后,进入`api`目录下可以看到`api.proto`和`api.pb.go`和`generate.go`文件,其中: +* `api.proto`是gRPC server的描述文件 +* `api.pb.go`是基于`api.proto`生成的代码文件 +* `generate.go`是用于`kratos tool`执行`go generate`进行代码生成的临时文件 + +接下来可以将以上三个文件全部删除或者保留`generate.go`,之后编写自己的proto文件,确认proto无误后,进行代码生成: +* 可直接执行`kratos tool kprotoc`,该命令会调用protoc工具生成`.pb.go`文件 +* 如`generate.go`没删除,也可以执行`go generate`命令,将调用`kratos tool kprotoc`工具进行代码生成 + +# 注册server + +进入`internal/server/grpc`目录,打开`server.go`文件,可以看到以下代码,只需要替换以下注释内容就可以启动一个gRPC服务。 + +```go +package grpc + +import ( + pb "kratos-demo/api" + "kratos-demo/internal/service" + "github.com/bilibili/kratos/pkg/conf/paladin" + "github.com/bilibili/kratos/pkg/net/rpc/warden" +) + +// New new a grpc server. +func New(svc *service.Service) *warden.Server { + var rc struct { + Server *warden.ServerConfig + } + if err := paladin.Get("grpc.toml").UnmarshalTOML(&rc); err != nil { + if err != paladin.ErrNotExist { + panic(err) + } + } + ws := warden.NewServer(rc.Server) + // 注意替换这里: + // RegisterDemoServer方法是在"api"目录下代码生成的 + // 对应proto文件内自定义的service名字,请使用正确方法名替换 + pb.RegisterDemoServer(ws.Server(), svc) + ws, err := ws.Start() + if err != nil { + panic(err) + } + return ws +} +``` + +### 注册注意 + +```go +// SayHello grpc demo func. +func (s *Service) SayHello(ctx context.Context, req *pb.HelloReq) (reply *empty.Empty, err error) { + reply = new(empty.Empty) + fmt.Printf("hello %s", req.Name) + return +} +``` + +请进入`internal/service`内找到`SayHello`方法,注意方法的入参和出参,都是按照gRPC的方法声明对应的: +* 第一个参数必须是`context.Context`,第二个必须是proto内定义的`message`对应生成的结构体 +* 第一个返回值必须是proto内定义的`message`对应生成的结构体,第二个参数必须是`error` +* 在http框架bm中,如果共用proto文件生成bm代码,那么也可以直接使用该service方法 + +建议service严格按照此格式声明方法,使其能够在bm和warden内共用 + +# client调用 + +请进入`internal/dao`方法内,一般对资源的处理都会在这一层封装。 +对于`client`端,前提必须有对应`proto`文件生成的代码,那么有两种选择: + +* 拷贝proto文件到自己项目下并且执行代码生成 +* 直接import服务端的api package + +***PS:这也是业务代码我们加了一层`internal`的关系,服务对外暴露的只有接口*** + +不管哪一种方式,以下初始化gRPC client的代码建议伴随生成的代码存放在统一目录下: + +```go +package dao + +import ( + "context" + + "github.com/bilibili/kratos/pkg/net/rpc/warden" + + "google.golang.org/grpc" +) + +// AppID unique app id for service discovery +const AppID = "your app id" + +// NewClient new member grpc client +func NewClient(cfg *warden.ClientConfig, opts ...grpc.DialOption) (DemoClient, error) { + client := warden.NewClient(cfg, opts...) + conn, err := client.Dial(context.Background(), "discovery://default/"+AppID) + if err != nil { + return nil, err + } + // 注意替换这里: + // NewDemoClient方法是在"api"目录下代码生成的 + // 对应proto文件内自定义的service名字,请使用正确方法名替换 + return NewDemoClient(conn), nil +} +``` + +其中,`"discovery://default/"+AppID`为gRPC target,提供给resolver用于discovery服务发现的,如果在使用其他服务发现组件,可以根据自己的实现情况传入。 + +有了初始化`Client`的代码,我们的`Dao`对象即可进行初始化和使用,以下以直接import服务端api包为例: + +```go +package dao + +import( + demoapi "kratos-demo/api" + grpcempty "github.com/golang/protobuf/ptypes/empty" + + "github.com/pkg/errors" +) + +type Dao struct{ + demoClient demoapi.DemoClient +} + +// New account dao. +func New(c *conf.Config) (d *Dao) { + d = &Dao{} + var err error + if d.demoClient, err = demoapi.NewClient(c.DemoRPC); err != nil { // NOTE: DemoRPC为warden包内的ClientConfig对象 + panic(err) + } + return +} + +// SayHello say hello. +func (d *Dao) SayHello(c context.Context, req *demoapi.HelloReq) (resp *grpcempty.Empty, err error) { + if resp, err = d.demoClient.SayHello(c, req); err != nil { + err = errors.Wrapf(err, "%v", arg) + } + return +} +``` + +如此在`internal/service`层就可以进行资源的方法调用。 + +# 扩展阅读 + +[warden拦截器](warden-mid.md) [warden基于pb生成](warden-pb.md) [warden服务发现](warden-resolver.md) [warden负载均衡](warden-balancer.md) + +------------- + +[文档目录树](summary.md) diff --git a/doc/wiki-cn/warden-resolver.md b/doc/wiki-cn/warden-resolver.md new file mode 100644 index 000000000..e69de29bb diff --git a/doc/wiki-cn/warden.md b/doc/wiki-cn/warden.md index e69de29bb..7eaaded5b 100644 --- a/doc/wiki-cn/warden.md +++ b/doc/wiki-cn/warden.md @@ -0,0 +1,49 @@ +# 背景 + +我们需要统一的rpc服务,经过选型讨论决定直接使用成熟的跨语言的gRPC。 + +# 概览 + +* 不改gRPC源码,基于接口进行包装集成trace、log、prom等组件 +* 打通自有服务注册发现系统[discovery](https://github.com/bilibili/discovery) +* 实现更平滑可靠的负载均衡算法 + +# 拦截器 + +gRPC暴露了两个拦截器接口,分别是: + +* `grpc.UnaryServerInterceptor`服务端拦截器 +* `grpc.UnaryClientInterceptor`客户端拦截器 + +基于两个拦截器可以针对性的定制公共模块的封装代码,比如`warden/logging.go`是通用日志逻辑。 + +[warden拦截器](warden-mid.md) + +# 服务发现 + +gRPC暴露了服务发现的接口`resolver.Resolver`,`warden/resolver/resolver.go`实现了该接口,并基于了`pkg/naming/naming.go`内的`Resolver`接口进行`Fetch``Watch`等操作。 + +`pkg/naming/discovery/discovery.go`内实现了`pkg/naming/naming.go`内的`Resolver`接口,使用[discovery](https://github.com/bilibili/discovery)来进行服务发现。 + +注意:`pkg/naming/naming.go`内的`Resolver`接口是`kratos`的一层封装,暴露的接口主要: + +* 相对原生`resolver.Resolver`内`ResolveNow`更友好的方法`Fetch``Watch` +* 统一应用的实例信息结构体`naming.Instance` + +想要用非[discovery](https://github.com/bilibili/discovery)的请参考下面文档进行开发。 + +[warden服务发现](warden-resolver.md) + +# 负载均衡 + +实现了`wrr`和`p2c`两种算法,默认使用`p2c`。 + +[warden负载均衡](warden-balancer.md) + +# 扩展阅读 + +[warden快速开始](warden-quickstart.md) [warden拦截器](warden-mid.md) [warden负载均衡](warden-balancer.md) [warden基于pb生成](warden-pb.md) [warden服务发现](warden-resolver.md) + +------------- + +[文档目录树](summary.md)