1 Star 0 Fork 0

distill / ditill-micro-grpc

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

微服务之GRpc

distill-infra集成了go-micro框架,在项目启动过程中,可以配置和启动GRpc进行服务之间的通信。

结构

distill-micro-grpc项目是一个简单的服务之间通过grpc进行通信的用例。

  • micro-gateway 对外保留http端口,接收请求,并通过grpc调用micro_prod_server服务的端口endpoint。
  • micro_prod_server对外暴露grpc端口协议。

依赖

工具依赖

Protoc v3.11.4 下载

protoc-go-inject-tag v1.0.0

go get -u github.com/favadi/protoc-go-inject-tag v1.0.0

项目依赖

gitee.com/banyanhouse/distill-infra v0.0.16 编写文档时为v0.0.16版本,建议使用最新发布的版本 github.com/golang/protobuf v1.4.2 github.com/micro/go-micro/v2 v2.5.0 github.com/sirupsen/logrus v1.4.2 golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 google.golang.org/genproto v0.0.0-20200521103424-e9a78aa275b7 // indirect google.golang.org/grpc v1.29.1

产品服务

创建服务提供的proto协议文件

创建商品模型

# micro_prod_server -> Services -> protos -> Models.proto
syntax = "proto3";
option go_package = ".;Services";
package Services;
// 商品模型 通过@inject_tag注解为返回体属性设置了tag,是为了修改符合接口定义的返回体重的json数据标签
message ProdModel {
  // @inject_tag: json:"pid"
  int32 ProdId = 1;
  // @inject_tag: json:"pname"
  string ProdName = 2;
}

创建商品服务

对外暴露的接口,是由iris/context的ReadJson来将获取到的数据存放于如下的请求体ProdsRequest中,所以通过@inject_tag设定了校验和json序列化标签。在后面我们用gen.bat批处理文件中,调用了提前安装好的protoc-go-inject-tag来对生成的pd文件中的标签进行了统一修改。

# micro_prod_server -> Services -> protos -> ProdService.proto
syntax="proto3";
option go_package = ".;Services";
package Services;
import "Models.proto";

message ProdsRequest {
  // @inject_tag: validate:"required" json:"size"
  int32 size = 1;
}

message ProdListResponse {
  repeated ProdModel data = 1;
}

service ProdService {
  rpc GetProdsList(ProdsRequest) returns (ProdListResponse);
}

创建proto编译批处理文件

# micro_prod_server -> gen.bat
cd Services/protos
protoc -I . --micro_out=../ --go_out=plugins=grpc:../ Models.proto
protoc --proto_path=. --proto_path=.. --micro_out=../ --go_out=plugins=grpc:../ ProdService.proto
protoc-go-inject-tag -input=../Models.pb.go
cd .. && cd ..

执行以上批处理文件,我们即可生成编译后的pd.go和pd.micro.go文件,目录结构如下

Services
-- protos
---- Models.proto
---- ProdService.proto
-- Models.pd.go
-- Models.pd.micro.go   # 该文件其实没有用,可以把批处理protoc第一行的 --micro_out=../ 去除,不再生成这个文件,因为Models.proto文件中,没有service的配置。
-- ProdService.pd.go
-- ProdService.pd.micro.go

在ProdService.pd.micro.go文件中,生成了RegisterProdServiceHandler函数,作为注册服务到注册中心的句柄函数。该函数内部接口prodService中的函数GetProdsList(ctx context.Context, in *ProdsRequest, out *ProdListResponse) error,就需要我们来编写实现,来对接收到的请求ProdsRequest进行处理,并通过ProdListResponse进行返回。具体实现如下,先创建一个独立的包ServiceImpl

package ServiceImpl

import (
	"context"
	"fmt"
	"gitee.com/banyanhouse/distill-micro-grpc/micro_prod_server/Services"
	"strconv"
)

type ProdService struct {

}

func (p *ProdService) GetProdsList(ctx context.Context, request *Services.ProdsRequest,
	response *Services.ProdListResponse) error {
	fmt.Printf("receive request:%d\n", request.Size)
	models := make([]*Services.ProdModel, 0)
    // 模拟数据取数场景
	var i int32
	for i=0; i<request.Size;i++{
		models = append(models, newProd(100+i, "prodName" + strconv.Itoa(100 + int(i))))
	}
	response.Data = models
	return nil
}

// 测试方法
func newProd(id int32, pname string) *Services.ProdModel {
	return &Services.ProdModel{
		ProdId:   id,
		ProdName: pname,
	}
}

通过micro_prod_server -> apis -> grpcapi -> ProdGrpc.go 来注册该grpc接口服务到注册中心:

package grpcapi


import (
	"fmt"
	"gitee.com/banyanhouse/distill-infra/apigrpc"
	"gitee.com/banyanhouse/distill-infra/register"
	"gitee.com/banyanhouse/distill-micro-grpc/micro_prod_server/ServiceImpl"
	"gitee.com/banyanhouse/distill-micro-grpc/micro_prod_server/Services"
	log "github.com/sirupsen/logrus"
)

func init() {
	apigrpc.RegisterGRpcApi(new(GRpcApi))
}

type GRpcApi struct {
}

func (g *GRpcApi) Init(grpcName, grpcPort string) {
	register.GRpcRegister(grpcName, grpcPort)
	// 获取框架go-micro的micro.Service,其内包含注册中心信息
	grpcService := register.GrpcService()
	// 通过RegisterProdServiceHandler将服务实现方法注册到注册中心中
	err := Services.RegisterProdServiceHandler(grpcService.Server(), new(ServiceImpl.ProdService))
	if err != nil {
		log.Errorf("GRpc Service impl failed:%s\n", err.Error())
	}
	// 打印查看中策中心的服务列表清单
	services, err := register.RegistryCenter().ListServices()
	if err != nil {
		log.Errorf("get registry service list failed. %s", err.Error())
	}
	for i, service := range services {
		fmt.Printf("%d -----> %s\n", i, service.Name)
	}
}

应用框架中需要在app.go中调用服务的初始化

package distill_micro_http

import (
	"fmt"
	infra "gitee.com/banyanhouse/distill-infra"
	"gitee.com/banyanhouse/distill-infra/apigrpc"
	"gitee.com/banyanhouse/distill-infra/base"
	"gitee.com/banyanhouse/distill-infra/hook"
	"gitee.com/banyanhouse/distill-infra/log"
	"gitee.com/banyanhouse/distill-infra/register"
	"gitee.com/banyanhouse/distill-infra/validator"
	_ "gitee.com/banyanhouse/distill-micro-grpc/micro_prod_server/apis/grpcapi" // 将注册grpc服务包在这里进行引入,注册服务。
)

func init() {
	fmt.Println("start app...")
	infra.Register(&base.TomlPropsStarter{})
	infra.Register(&log.LoggerStarter{}) // 如果需要输出日志到文件中,则可以打开这里,去初始化文件日志
	infra.Register(&validator.ValidatorStarter{})
	infra.Register(&register.Etcd3Starter{})
	infra.Register(&apigrpc.GRpcApiStarter{}) // 启动distill-infra框架的GRpc启动器
	infra.Register(&hook.HookStarter{})
	fmt.Println("load end ...")
}

配置信息

[app]
name = "micro_prod_server"
port = 18186
protocol = "grpc" #grpc http https
time = "10s"
testing = false
...

网关调用服务

将micro_prod_server -> Services -> protos下的proto文件复制到micro-gateway -> Services -> protos文件夹中,同时将gen.bat也复制到micro-gateway项目的根路径中,执行生成pd.go和pd.micro.go文件。

编写一个Web路由,调用注册中心的grpc微服务。

package web

import (
	"context"
	"gitee.com/banyanhouse/distill-infra/api"
	"gitee.com/banyanhouse/distill-infra/validator"
	"gitee.com/banyanhouse/distill-infra/web"
	"gitee.com/banyanhouse/distill-micro-grpc/micro-gateway/Services"
	irisContext "github.com/kataras/iris/context"
	"github.com/micro/go-micro/v2"
	log "github.com/sirupsen/logrus"
)

func init() {
	api.SetupApi(new(ProdsHandler))
}

type ProdsHandler struct {
}

func (c *ProdsHandler) Init() {
}

func (c *ProdsHandler) Setup() {
	// 路由注册
	groupRouter := web.IrisMainParty().Party("/v1/micro/grpc")
	groupRouter.Post("/prod", ProdHandler)
}

func ProdHandler(ctx irisContext.Context)  {
	var (
		res web.Res
	)
	// 开启一个go-micro服务调用客户端
	myService := micro.NewService(
		micro.Name("prod.client"),
	)
	// 声明注册中心micro_prod_server服务
	prodService := Services.NewProdService(
		"micro_prod_server",
		myService.Client(),
	)

	var prodsRequest Services.ProdsRequest
	// 接收客户端请求,以json形式加载到请求体
	err := ctx.ReadJSON(&prodsRequest)
	// 验证请求体内容
	validatorErr := validator.ValidateStruct(&prodsRequest)
	if err != nil || validatorErr != nil {
		errRes(err, validatorErr, &res)
		ctx.JSON(&res)
		return
	}
	// 调用微服务接口
	prodsList, err := prodService.GetProdsList(context.Background(), &prodsRequest)

	if err != nil {
		errRes(err, nil, &res)
		ctx.JSON(&res)
		return
	}
	// 响应REST数据
	res = web.Res{
		Code: web.ResCodeOk,
		Message: "商品列表",
		Data: prodsList.GetData(),
	}
	ctx.JSON(&res)

}
// 错误异常处理
func errRes(err error, validatorErr error, res *web.Res) {
	var paramErr error
	if err != nil {
		paramErr = err
	}
	if validatorErr != nil {
		paramErr = validatorErr
	}
	log.Error(paramErr)
	res.Code = web.ResCodeRequestParamsError
	res.Message = "参数错误:" + paramErr.Error()
}

配置文件

[app]
name = "micro_gateway"
port = 18081
protocol = "http" #grpc http https
time = "10s"
testing = false
...

测试

image-20200602094408731

控制台输出

micro-gateway输出:

image-20200602124717143

micro_prod_server输出:

image-20200602124823863

空文件

简介

该模块是使用distill-infra框架,实现网关服务通过grpc调用产品服务的简单接口样例。 展开 收起
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/banyanhouse/ditill-micro-grpc.git
git@gitee.com:banyanhouse/ditill-micro-grpc.git
banyanhouse
ditill-micro-grpc
ditill-micro-grpc
master

搜索帮助