什么是 Go kit?
Go是一种很棒的通用语言,但是微服务需要一定量的专业支持。 RPC安全性,系统可观察性,基础结构集成甚至程序设计。Go kit 填补了标准库留下的空白,并使 Go 成为在任何组织中编写微服务的一流语言
下面基于go-kit实现用户微服务,用户的登陆,注册和获取用户信息,使用jwt方式来加密和解码,本文事例比较简单,主要是实现微服务和理解微服务开发,通信使用grpc服务来编码和解码
涉及到技术的如下:
1.grpc
2.consul 服务注册与发现
3.golang/rate 服务限流
4.中间价
5.身份验证jwt
6.ctx context.Context 上下文传递全局参数
代码结构如下:
1.首先定义proto文件
我们需要实现三个方法分别是 RegistAccount,LoginAccount,GetUserInfoByToken 分别是注册,登陆和通过token获取用户,和其他请求体,相信代码如下:
syntax = "proto3";
package pb;
service UserServiceExt {
// 注册用户
rpc RegistAccount(RegistAccountReq) returns(RegistAccountRsp) {}
// 用户登录
rpc LoginAccount(LoginAccountReq) returns(LoginAccountRsp) {}
// 通过token 获取用户信息
rpc GetUserInfoByToken(GetUserInfoByTokenRequest) returns(GetUserInfoByTokenResponse) {}
}
message RegistAccountReq {
string email = 1 ;
string userName = 2 ;
string password = 3 ;
}
message RegistAccountRsp {
int64 code = 1;
}
message LoginAccountReq {
string email = 1 ;
string password = 2 ;
}
message UserInfo {
int64 user_id=1;
string userName=2;
string email=3;
string phone=4;
}
message LoginAccountRsp {
int64 code = 1;
string token = 2;
string uid = 3;
}
message GetUserInfoByTokenRequest {
string token=1;
}
message GetUserInfoByTokenResponse {
int64 code=1;
UserInfo userInfo=3;
}
定义好ptoto 文件后 使用ptotoc工具生产服务端和客服端代码 我是放在/common/pb文件下,你可以定义你自己的生成路径:protoc --proto_path=./pb --go_out=plugins=grpc:./common/pb ./pb/*.proto
2.接下来我们来实现接口
在 service 文件下定义 并实现接口,详细代码如下
package service
import (
"context"
"fmt"
"go.uber.org/zap"
"mSystem/src/common/db"
"mSystem/src/common/errors"
"mSystem/src/common/pb"
"mSystem/src/utils"
)
type UserService interface {
RegistAccount(ctx context.Context, req *pb.RegistAccountReq) (*pb.RegistAccountRsp, error)
LoginAccount(ctx context.Context, req *pb.LoginAccountReq) (*pb.LoginAccountRsp, error)
GetUserInfoByToken(ctx context.Context, req *pb.GetUserInfoByTokenRequest) (*pb.GetUserInfoByTokenResponse, error)
}
type baseServer struct {
logger *zap.Logger
}
func NewUserService(log *zap.Logger) UserService {
var server UserService
server = &baseServer{
logger: log,
}
//server = NewLogMiddlewareServer(log)(server)
return server
}
// 账户注册
func (u baseServer) RegistAccount(ctx context.Context, req *pb.RegistAccountReq) (*pb.RegistAccountRsp, error) {
userName := req.UserName
password := req.Password
email := req.Email
user, err := db.SelectUserByEmail(email)
if err != nil {
u.logger.Error("error", zap.Error(err))
return &am