基于go-micro微服务的实战-使用go-micro实现用户服务(二)

基于go-micro微服务的实战-使用go-micro实现用户服务(二)

文章最后附带完整代码

基于go-micro搭建简单用户服务
创建好服务目录,在第一节工程目录上迭代

目录

  • common: 公告模块,配置初始化等
  • conf: 配置文件
  • handler: 服务的业务逻辑处理
  • models: 数据库操作
  • pbfile: 存放proto编译后文件
  • proto: proto文件
  • utils: 工具目录
  • wrapper: 装饰器(中间件)处理

其它相关的.bat.sh是window和linux下快速执行的执行文件而已,方便使用,无特殊意义。

第一步:配置文件,编写service.conf
##consul注册发现
consul_addr = "127.0.0.1"
consul_port = 8500

##mysql数据库
mysql_addr = "127.0.0.1"
mysql_port = 3306
mysql_user = "root"
mysql_pwd = "123789"
mysql_db_name = "emicro"
第二步:proto文件,编写user.proto
syntax = "proto3";
option go_package = "../pbfile";

package proto;

//声明服务
service UserService{
    //声明方法
    rpc TestUser(TestReq) returns(TestResp){}
}

message TestReq{
    int32 id = 1;
}

message TestResp{
    string msg = 1;
}

编写快速生成文件,不用每次都手打protoc编译命令,打开pb.bat,把编译后文件指定生成到pbfile目录。

protoc --go_out=../pbfile --micro_out=../pbfile "*".proto

编写完毕,执行pb.bat,会在pbfile目录下生成user.pb.gouser.pb.micro.go

第三步:编写服务和服务处理逻辑,server.go和user_handler.go

启动服务:

    service := common.NewService()

	//服务注册
	consulRegis := consul.NewRegistry( func(options *registry.Options){
		//读取配置的consul服务器地址
        addr := common.Config.String("consul_addr")
		port, _ := common.Config.Int("consul_port")
		addrs := fmt.Sprintf("%v:%d", addr, port)
		options.Addrs = []string{
			addrs,
		}
	})

	//创建服务,这里不指定服务器ip和端口,通过参数接收,方便扩容
    service.Service = micro.NewService(
		micro.Name(common.ServerName),
		micro.Registry(consulRegis),
	)

    //注册服务和处理器
	pb.RegisterUserServiceHandler(service.Service.Server(), handler.NewUserHandler(service))

	//接收命令参数,端口
	service.Service.Init()

	//解析服务Addr
	common.InitAddr(service)

	service.Service.Run()

逻辑处理器,user_handler.go:

type UserHandler struct {
	service *common.EmicroService
}

//grpc服务接收处理
func (u *UserHandler) TestUser(ctx context.Context, req *pb.TestReq, resp *pb.TestResp) error {
	log.Println(req.Id)
	resp.Msg = "success"
	return nil
}

//创建处理器
func NewUserHandler(service *common.EmicroService) *UserHandler{
	handler:= new(UserHandler)
	handler.service = service
	return handler
}
第四步:连接mysql服务器,之后备用,models/base.go

这里用gorm库来操作

var Db *gorm.DB

func init(){
	addr := common.Config.String("mysql_addr")
	port, _ := common.Config.Int("mysql_port")
	user := common.Config.String("mysql_user")
	pwd := common.Config.String("mysql_pwd")
	db_name := common.Config.String("mysql_db_name")
	dsn := fmt.Sprintf("%v:%v@tcp(%v:%d)/%v?charset=utf8mb4&parseTime=True&loc=Local",
		user, pwd, addr, port, db_name)
	Db1, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		NamingStrategy: schema.NamingStrategy{
			SingularTable: true,  //禁用表名复数
		},
	})
	if err!=nil{
		log.Println("Init Gorm Err:", err)
	}
	log.Println("Init Success")
	Db = Db1
}
第五步:编写装饰器

当前服务作为客户端请求其它服务的client_wrapper.go和服务端接收请求处理的server_wrapper.go装饰器

譬如可以对请求做统计,日志输出,监听等处理操作,跟grpc的拦截器类似。之后处理全链路追踪也是基于装饰器。

client_wrapper.go

type CliWrapper struct {
	client.Client
}

func (c *CliWrapper) Call(ctx context.Context, req client.Request, rsp interface{}, opts ...client.CallOption) error{
	log.Println("client wrapper!!!")
	return c.Client.Call(ctx, req, rsp, opts...)
}

func NewCliWrapper(c client.Client) client.Client{
	return &CliWrapper{c}
}

server_wrapper.go

//服务端装饰器
func ServerWrapper() server.HandlerWrapper{
	return func(h server.HandlerFunc) server.HandlerFunc {
		return func(ctx context.Context, req server.Request, rsp interface{}) error {
			log.Println("Server wrapper!!!")
			return h(ctx, req, rsp)
		}
	}
}

要在上面第三步服务启动时候声明装饰器

	service.Service = micro.NewService(
		micro.Name(common.ServerName),
		micro.Registry(consulRegis),
		micro.WrapHandler(wrapper.ServerWrapper()),  //服务端接收处理装饰器
		micro.WrapClient(wrapper.NewCliWrapper),     //客户端请求装饰器
	)
第六步:启动服务

编写user.bat快速启动服务,需要传递服务的Ip地址和端口参数

go run server.go --server_address 0.0.0.0:5500

出现以下内容则说的启动和注册服务成功

启动服务

最后一步:测试服务,编写客户端请求用户服务

具体目录为user_client

	consulRegis := consul.NewRegistry(func(options *registry.Options) {
		options.Addrs = []string{
			"127.0.0.1:8500",
		}
	})

	service := micro.NewService(
		micro.Name("emicro.user.client"),
		micro.Registry(consulRegis),
	)
	userService := pb.NewUserService("emicro.user", service.Client())
	res, err := userService.TestUser(context.TODO(), &pb.TestReq{Id:1150})
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(res)

出现如下,代表请求和响应成功

测试


注意:尽量用module依赖管理,并且使用的是go-micro v3,如果用v2会有奇奇怪怪问题和编译不通过等,可参考使用完整代码import的库。

gitee完整代码链接

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值