go微服務框架kratos學習筆記四(kratos warden-quickstart warden-direct方式client調用)

go微服務框架kratos學習筆記四(kratos warden-quickstart warden-direct方式client調用)


warden direct

本文是學習kratos warden第一節,kratos warden的直連方式client調用,我直接用demo項目作示例github

demo-server

先建立一個用做grpc-servergolang

kratos new grpc-server

在建立一個調用grpc-server接口的call-serverredis

kratos new call-server

如今該目錄下有兩個服務sql

[I:\VSProject\kratos-note\warden\direct]$ tree
卷 辦公 的文件夾 PATH 列表
卷序列號爲 00650064 0007:32FD
I:.
├─call-server
│  ├─api
│  ├─cmd
│  ├─configs
│  ├─internal
│  │  ├─dao
│  │  ├─di
│  │  ├─model
│  │  ├─server
│  │  │  ├─grpc
│  │  │  └─http
│  │  └─service
│  └─test
└─grpc-server
    ├─api
    ├─cmd
    ├─configs
    ├─internal
    │  ├─dao
    │  ├─di
    │  ├─model
    │  ├─server
    │  │  ├─grpc
    │  │  └─http
    │  └─service
    └─test

咱們後面用call-server直連 grpc-server 調用grpc接口。api

grpc.toml

配置裏面修改下端口,同時call-server裏面添加grpc-server的地址,我這是9003.app

[Server]
    addr = "0.0.0.0:9004"
    timeout = "1s"
    
[Client]
    addr = "0.0.0.0:9003"
    timeout = "1s"

服務註冊

grpc-server的internal/server/grpc目錄打開server.go文件,能夠看到如下代碼,替換註釋內容就能夠啓動一個gRPC、咱們就是demo項目不須要替換。框架

package grpc

import (
    pb "grpc-server/api"

    "github.com/bilibili/kratos/pkg/conf/paladin"
    "github.com/bilibili/kratos/pkg/net/rpc/warden"
)

// New new a grpc server.
func New(svc pb.DemoServer) (ws *warden.Server, err error) {
    var (
        cfg warden.ServerConfig
        ct paladin.TOML
    )
    if err = paladin.Get("grpc.toml").Unmarshal(&ct); err != nil {
        return
    }
    if err = ct.Get("Server").UnmarshalTOML(&cfg); err != nil {
        return
    }
    ws = warden.NewServer(&cfg)
    // 注意替換這裏:
    // RegisterDemoServer方法是在"api"目錄下代碼生成的
    // 對應proto文件內自定義的service名字,請使用正確方法名替換
    pb.RegisterDemoServer(ws.Server(), svc)
    ws, err = ws.Start()
    return
}

接着直接啓動grpc-serveride

kratos run
I:/VSProject/go/pkg/mod/github.com/bilibili/kratos@v0.3.2-0.20191224125553-6e1180f53a8e/pkg/net/rpc/warden/server.go:329 warden: start grpc listen addr: [::]:9003

服務發現

client端要調用grpc的接口必須有它生成的protobuf文件微服務

通常是下面兩種方式:

一、拷貝proto文件到本身項目下而且執行代碼生成
二、直接import服務端的api package

這裏由於demo服務api如出一轍,我就不作import了,直接取api裏面的pb.go文件

internal/dao 裏面直接修改dao文件並添加一個direct_client.go

direct_client.go
其中,target爲gRPC用於服務發現的目標,使用標準url資源格式提供給resolver用於服務發現。warden默認使用direct直連方式,直接與server端進行鏈接。其餘服務發現方式下回見。

package dao

import (
    "context"

    "github.com/bilibili/kratos/pkg/net/rpc/warden"

    "google.golang.org/grpc"
)

// target server addrs.
const target = "direct://default/127.0.0.1:9003" // NOTE: example

// 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(), target)
    if err != nil {
        return nil, err
    }
    // 注意替換這裏:
    // NewDemoClient方法是在"api"目錄下代碼生成的
    // 對應proto文件內自定義的service名字,請使用正確方法名替換
    return NewDemoClient(conn), nil
}

client direct 調用

dao.go 改爲以下。
添加一個dao裏面直接demoClient,newDao裏面作democlient的初始化、並添加一個SayHello接口。

package dao

import (
    "context"
    "time"

    demoapi "call-server/api"
    "call-server/internal/model"

    "github.com/bilibili/kratos/pkg/cache/memcache"
    "github.com/bilibili/kratos/pkg/cache/redis"
    "github.com/bilibili/kratos/pkg/conf/paladin"
    "github.com/bilibili/kratos/pkg/database/sql"
    "github.com/bilibili/kratos/pkg/net/rpc/warden"
    "github.com/bilibili/kratos/pkg/sync/pipeline/fanout"
    xtime "github.com/bilibili/kratos/pkg/time"
    grpcempty "github.com/golang/protobuf/ptypes/empty"
    "github.com/pkg/errors"

    "github.com/google/wire"
)

var Provider = wire.NewSet(New, NewDB, NewRedis, NewMC)

//go:generate kratos tool genbts
// Dao dao interface
type Dao interface {
    Close()
    Ping(ctx context.Context) (err error)
    // bts: -nullcache=&model.Article{ID:-1} -check_null_code=$!=nil&&$.ID==-1
    Article(c context.Context, id int64) (*model.Article, error)
    SayHello(c context.Context, req *demoapi.HelloReq) (resp *grpcempty.Empty, err error)
}

// dao dao.
type dao struct {
    db         *sql.DB
    redis      *redis.Redis
    mc         *memcache.Memcache
    demoClient demoapi.DemoClient
    cache      *fanout.Fanout
    demoExpire int32
}

// New new a dao and return.
func New(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d Dao, cf func(), err error) {
    return newDao(r, mc, db)
}

func newDao(r *redis.Redis, mc *memcache.Memcache, db *sql.DB) (d *dao, cf func(), err error) {
    var cfg struct {
        DemoExpire xtime.Duration
    }
    if err = paladin.Get("application.toml").UnmarshalTOML(&cfg); err != nil {
        return
    }

    grpccfg := &warden.ClientConfig{}
    paladin.Get("grpc.toml").UnmarshalTOML(grpccfg)
    var grpcClient demoapi.DemoClient
    if grpcClient, err = NewClient(grpccfg); err != nil {
        return
    }

    d = &dao{
        db:         db,
        redis:      r,
        mc:         mc,
        demoClient: grpcClient,
        cache:      fanout.New("cache"),
        demoExpire: int32(time.Duration(cfg.DemoExpire) / time.Second),
    }
    cf = d.Close
    return
}

// Close close the resource.
func (d *dao) Close() {
    d.cache.Close()
}

// Ping ping the resource.
func (d *dao) Ping(ctx context.Context) (err error) {
    return nil
}

// 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", req.Name)
    }
    return
}

service.go裏面調用dao.SayHello()

// SayHello grpc demo func.
func (s *Service) SayHello(ctx context.Context, req *pb.HelloReq) (reply *empty.Empty, err error) {
    reply = new(empty.Empty)
    s.dao.SayHello(ctx, req)
    fmt.Printf("hello %s", req.Name)
    return
}

最後調用call-server的http接口測試:

從grpc-server的日誌裏面能夠看到咱們的調用是成功的, 本節完(๑′ᴗ‵๑)I Lᵒᵛᵉᵧₒᵤ❤。

本例子源代碼 :https://github.com/ailumiyana/kratos-note

相關文章
相關標籤/搜索