consul-在项目中使用
一. 在python项目中使用
1.目录存放
创建公共目录存放common/register,创建base.py register.py

2.base.py基础类
import abc
class Resister(metaclass=abc.ABCMeta):
@abc.abstractmethod
def register(self, name, id, address, port):
pass
@abc.abstractmethod
def deregister(self, service_id):
pass
@abc.abstractmethod
def get_all_service(self):
pass
@abc.abstractmethod
def filter_service(self, f):
pass
3. 注册文件consul.py
import requests
from common.register import base
import consul
class ConsulRegister(base.Resister):
def __int__(self, host, port):
self.host = host
self.port = port
self.c = consul.Consul(host=host, port=port)
def register(self, name, id, address, port):
check = {
"GRPC": f"{address}:{port}",
"GRPCUseTLS": False,
"Timeout": "5s",
"Interval": "5s",
"DeregisterCriticalServiceAfter": "15s"
}
# 注册
return self.c.agent.service.register(name="user-srv", service_id="user-srv2",
address=address, port=port, tags=["mxshop"], check=check)
def deregister(self, service_id):
return self.c.agent.service.deregister(service_id)
def get_all_service(self):
return self.c.agent.services()
def filter_service(self, f):
url = f"http://{self.host}:{self.port}/v1/agent/services"
params = {
"filter": f
}
rsp = requests.get(url, params=params).json()
return rsp
4. 使用
在server.py中使用
logger.info(f"服务注册开始")
register = consul.ConsulRegister(settings.CONSUL_HOST, settings.CONSUL_POST)
if not register.register(name=settings.SERVICE_NAME, id=settings.SERVICE_NAME, address=args.ip, port=args.port,
tags=settings.SERVICE_TAGS):
logger.info(f"服务注册失败")
sys.exit(0)
logger.info(f"服务注册成功")
添加配置文件内容settings.py
# consul的配置
CONSUL_HOST = data["consul"]["host"]
CONSUL_PORT = data["consul"]["port"]
# 服务相关的配置
SERVICE_NAME = data["name"]
SERVICE_TAGS = data["tags"]
二. 在go-gin项目中使用
1. 配置文件
在config-debug.yaml中添加配置
consul:
host: '127.0.0.1'
port: 8500
在config/config.go中添加配置
type ConsulConfig struct {
Host string `mapstructure:"host"`
Port int `mapstructure:"port"`
}
type ServerConfig struct {
Name string `mapstructure:"name"`
Port int `mapstructure:"port"`
UserSrvInfo UserSrvConfig `mapstructure:"user_srv"`
JWTInfo JWTConfig `mapstructure:"jwt"`
AliSmsConfig AliSmsConfig `mapstructure:"sms"`
RedisConfig RedisConfig `mapstructure:"redis"`
ConsulInfo ConsulConfig `mapstructure:"consul"`
}
目录结构
2. 使用
在api/user.go中添加注册信息
//从注册中心获取到用户服务的信息
cfg := api.DefaultConfig()
//cfg.Address = "192.168.1.103:8500"
cfg.Address = fmt.Sprintf("%s:%d", global.ServerConfig.ConsulInfo.Host, global.ServerConfig.ConsulInfo.Port)
userSrvHost := ""
userSrvPost := 0
client, err := api.NewClient(cfg)
if err != nil {
panic(err)
}
data, err := client.Agent().ServicesWithFilter(fmt.Sprintf(`Service == "%s"`, global.ServerConfig.UserSrvInfo.Name))
if err != nil {
panic(err)
}
for _, value := range data {
userSrvHost = value.Address
userSrvPost = value.Port
break
}
if userSrvHost == "" {
ctx.JSON(http.StatusOK, gin.H{
"msg": "用户服务错误",
})
}
文件全部内容
package api
import (
"context"
"fmt"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"github.com/go-playground/validator/v10"
"github.com/go-redis/redis/v8"
"github.com/hashicorp/consul/api"
"go.uber.org/zap"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials/insecure"
"google.golang.org/grpc/status"
"mxshop-api/user-web/forms"
"mxshop-api/user-web/global"
"mxshop-api/user-web/global/reponse"
"mxshop-api/user-web/middlewares"
"mxshop-api/user-web/models"
"mxshop-api/user-web/proto"
"net/http"
"strconv"
"strings"
"time"
)
func removeTopStruct(fileds map[string]string) map[string]string {
rsp := map[string]string{}
for field, err := range fileds {
rsp[field[strings.Index(field, ".")+1:]] = err
}
return rsp
}
func HandleGrpcErrorToHttp(err error, c *gin.Context) {
// 将GRPC的code转换成HTTP的状态码
if err != nil {
if e, ok := status.FromError(err); ok {
switch e.Code() {
case codes.NotFound:
c.JSON(http.StatusNotFound, gin.H{
"msg": e.Message(),
})
case codes.Internal:
c.JSON(http.StatusInternalServerError, gin.H{
"msg": "内部错误",
})
case codes.InvalidArgument:
c.JSON(http.StatusBadRequest, gin.H{
"msg": "参数错误",
})
case codes.Unavailable:
c.JSON(http.StatusInternalServerError, gin.H{
"msg": "用户服务不可用",
})
default:
c.JSON(http.StatusInternalServerError, gin.H{
"msg": "其他错误",
})
}
return
}
}
}
func HandleValidatorError(ctx *gin.Context, err error) {
//定义统一返回的报错处理
errs, ok := err.(validator.ValidationErrors)
if !ok {
ctx.JSON(http.StatusOK, gin.H{
"msg": err.Error(),
})
}
ctx.JSON(http.StatusBadRequest, gin.H{
"error": removeTopStruct(errs.Translate(global.Trans)),
})
return
}
func GetUserList(ctx *gin.Context) {
//获取用户列表页的接口
//ip := "127.0.0.1"
//port := "50051"
//从注册中心获取到用户服务的信息
cfg := api.DefaultConfig()
//cfg.Address = "192.168.1.103:8500"
cfg.Address = fmt.Sprintf("%s:%d", global.ServerConfig.ConsulInfo.Host, global.ServerConfig.ConsulInfo.Port)
userSrvHost := ""
userSrvPost := 0
client, err := api.NewClient(cfg)
if err != nil {
panic(err)
}
data, err := client.Agent().ServicesWithFilter(fmt.Sprintf(`Service == "%s"`, global.ServerConfig.UserSrvInfo.Name))
if err != nil {
panic(err)
}
for _, value := range data {
userSrvHost = value.Address
userSrvPost = value.Port
break
}
if userSrvHost == "" {
ctx.JSON(http.StatusOK, gin.H{
"msg": "用户服务错误",
})
}
//拨号连接用户RPC服务
userConn, err := grpc.Dial(fmt.Sprintf("%s:%d", userSrvHost, userSrvPost), grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
zap.S().Errorw("[GetUserList]连接失败【用户服务失败】", "msg", err.Error())
}
claims, _ := ctx.Get("claims")
currentUser := claims.(*models.CustomClaims).ID
zap.S().Infof("访问用户:%d", currentUser)
//获取前端用户传递的参数
pn := ctx.DefaultQuery("pn", "0")
pnInt, _ := strconv.Atoi(pn)
pSize := ctx.DefaultQuery("psize", "10")
pSizeInt, _ := strconv.Atoi(pSize)
fmt.Println(pSizeInt)
//生成grpc的client并调用接口
userSrvClient := proto.NewUserClient(userConn)
rsp, err := userSrvClient.GetUserList(context.Background(), &proto.PageInfo{
Pn: int32(pnInt),
PSize: int32(pSizeInt),
})
if err != nil {
zap.S().Errorw("[GetUserList]查询用户列表失败")
HandleGrpcErrorToHttp(err, ctx)
return
}
result := make([]interface{}, 0)
for _, value := range rsp.Data {
user := reponse.UserResponse{
Id: value.Id,
NickName: value.NickName,
BirthDay: reponse.JsonTime(time.Unix(int64(value.BirthDay), 0)),
//BirthDay: time.Unix(int64(value.BirthDay), 0).Format("2022-01-01"),
//BirthDay: time.Unix(int64(value.BirthDay), 0),
Gender: value.Gender,
Mobile: value.Mobile,
}
result = append(result, user)
}
ctx.JSON(http.StatusOK, result)
}
func PassWordLogin(ctx *gin.Context) {
//密码登录的接口
//1.表单验证, 在forms中定义
//ctx.JSON(http.StatusOK, "密码登录")
passWordLoginForm := forms.PassWordLoginForm{}
//固定格式
if err := ctx.ShouldBind(&passWordLoginForm); err != nil {
HandleValidatorError(ctx, err)
return
}
if !store.Verify(passWordLoginForm.CaptchaId, passWordLoginForm.Captcha, true) {
ctx.JSON(http.StatusBadRequest, gin.H{
"captcha": "验证码错误",
})
return
}
//拨号连接用户RPC服务
userConn, err := grpc.Dial(fmt.Sprintf("%s:%d", global.ServerConfig.UserSrvInfo.Host, global.ServerConfig.UserSrvInfo.Port), grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
zap.S().Errorw("[GetUserList]连接失败【用户服务失败】", "msg", err.Error())
}
//生成grpc的client并调用接口
userSrvClient := proto.NewUserClient(userConn)
// 登录的逻辑, 查询是否存在,密码是否相等
if rsp, err := userSrvClient.GetUserByMobile(context.Background(), &proto.MobileRequests{
Mobile: passWordLoginForm.Mobile,
}); err != nil {
if e, ok := status.FromError(err); ok {
switch e.Code() {
case codes.NotFound:
ctx.JSON(http.StatusBadRequest, map[string]string{
"mobile": "用户不存在",
})
default:
ctx.JSON(http.StatusBadRequest, map[string]string{
"mobile": "登录失败",
})
}
return
}
} else {
// 只是查询了用户而已,并没有检查密码
if passRsp, pasErr := userSrvClient.CheckPassWord(context.Background(), &proto.PasswordCheckInfo{
Password: passWordLoginForm.PassWord,
EncryptedPassword: rsp.PassWord,
}); pasErr != nil {
ctx.JSON(http.StatusInternalServerError, map[string]string{
"password": "登录失败",
})
} else {
if passRsp.Success {
//生成token
j := middlewares.NewJWT()
claims := models.CustomClaims{
ID: uint(rsp.Id),
NickName: rsp.NickName,
AuthorityId: uint(rsp.Role),
StandardClaims: jwt.StandardClaims{
NotBefore: time.Now().Unix(), //签名的生效时间
ExpiresAt: time.Now().Unix() + 60*60*24*30, //30day过期
Issuer: "wanghui",
},
}
token, err := j.CreateToken(claims)
if err != nil {
ctx.JSON(http.StatusInternalServerError, map[string]string{
"msg": "生成token失败",
})
return
}
ctx.JSON(http.StatusOK, gin.H{
"id": rsp.Id,
"nick_name": rsp.NickName,
"token": token,
"expired_at": time.Now().Unix() + 60*60*24*30*1000,
})
} else {
ctx.JSON(http.StatusBadRequest, map[string]string{
"msg": "登录失败",
})
}
}
}
}
func Register(ctx *gin.Context) {
// 用户注册
//表单验证, 在forms中定义
registerForm := forms.RegisterForm{}
//固定格式
if err := ctx.ShouldBind(®isterForm); err != nil {
HandleValidatorError(ctx, err)
return
}
//验证码校验
rdb := redis.NewClient(&redis.Options{
Addr: fmt.Sprintf("%s:%d", global.ServerConfig.RedisConfig.Host, global.ServerConfig.RedisConfig.Port),
})
//key , values , 过期时间
value, err := rdb.Get(context.Background(), registerForm.Mobile).Result()
if err == redis.Nil {
fmt.Println("key不存在")
ctx.JSON(http.StatusBadRequest, gin.H{
"msg": "验证码错误",
})
return
} else {
if value != registerForm.Code {
ctx.JSON(http.StatusBadRequest, gin.H{
"msg": "验证码错误",
})
return
}
}
//拨号连接用户RPC服务
userConn, err := grpc.Dial(fmt.Sprintf("%s:%d", global.ServerConfig.UserSrvInfo.Host, global.ServerConfig.UserSrvInfo.Port), grpc.WithTransportCredentials(insecure.NewCredentials()))
if err != nil {
zap.S().Errorw("[GetUserList]连接失败【用户服务失败】", "msg", err.Error())
}
//生成grpc的client并调用接口
userSrvClient := proto.NewUserClient(userConn)
user, err := userSrvClient.CreateUser(context.Background(), &proto.CreateUserInfo{
NickName: registerForm.Mobile,
PassWord: registerForm.PassWord,
Mobile: registerForm.Mobile,
})
if err != nil {
zap.S().Errorw("[Register]注册【 新建用户失败】失败:%s", err.Error())
HandleGrpcErrorToHttp(err, ctx)
return
}
//注册成功后,生成token
j := middlewares.NewJWT()
claims := models.CustomClaims{
ID: uint(user.Id),
NickName: user.NickName,
AuthorityId: uint(user.Role),
StandardClaims: jwt.StandardClaims{
NotBefore: time.Now().Unix(), //签名的生效时间
ExpiresAt: time.Now().Unix() + 60*60*24*30, //30day过期
Issuer: "wanghui",
},
}
token, err := j.CreateToken(claims)
if err != nil {
ctx.JSON(http.StatusInternalServerError, map[string]string{
"msg": "生成token失败",
})
return
}
ctx.JSON(http.StatusOK, gin.H{
"id": user.Id,
"nick_name": user.NickName,
"token": token,
"expired_at": time.Now().Unix() + 60*60*24*30*1000,
})
}

浙公网安备 33010602011771号