• 一个基于 gin+ grpc + etcd 等框架开发的小栗子


    一、标准的项目结构

    首先我们看一个标准的项目结构是什么样子的,github 上给出的一个示例:golang-standards/project-layout

     

     

    二、服务注册与发现流程

    三、etcd官方示例

    服务注册和发现都可参考 etcd官网 的注册和发现流程。

    1、服务注册

     2、取消注册

     3、使用租约注册(类似于ZooKeeper的临时节点)

     4、事务更新

     5、服务发现

    四、grpc官方示例

    如何启动和调用一个 gRPC 服务,可参考 gRPC官网

    1、启动 gRPC 服务(需要用到ProtoBuf)

    2、创建 gRPC 客户端(需要用到ProtoBuf)

     3、调用 gRPC 服务方法(需要用到ProtoBuf)

    五、示例代码

    项目地址:gRPC-GoWeb

    1、服务注册。

     1、连接etcd注册中心

    复制代码
    func New(etcdAddr []string) (*EtcdRegister, error) {
        log.Printf("开始连接etcd注册中心... \n")
        cli, err := clientv3.New(clientv3.Config{
            Endpoints:   etcdAddr,
            DialTimeout: 5 * time.Second,
        })
        if err != nil {
            log.Printf("连接etcd注册中心失败,失败原因是: %v \n", err)
            return nil, err
        }
        log.Printf("连接etcd注册中心成功! \n")
        return &EtcdRegister{
            cli: cli,
        }, nil
    }
    复制代码

    2、服务注册

    复制代码
    func (etcdRegister *EtcdRegister) Register(srvName string, srvAddr string, ttl int64) error {
        etcdRegister.srvName = srvName
        etcdRegister.srvAddr = srvAddr
        log.Printf("开始创建etcd端点管理器... \n")
        em, err := endpoints.NewManager(etcdRegister.cli, srvName)
        if err != nil {
            log.Printf("创建etcd端点管理器失败,失败原因是: %v \n", err)
            return err
        }
        etcdRegister.em = em
        log.Printf("创建etcd端点管理器成功! \n")
        log.Printf("开始创建服务租期... \n")
        lease, err := etcdRegister.cli.Grant(context.TODO(), ttl)
        if err != nil {
            log.Printf("创建服务租期失败,失败原因是: %v", err)
        }
        etcdRegister.ttl = ttl
        etcdRegister.leaseID = lease.ID
        log.Printf("创建服务租期成功! \n")
        log.Printf("开始注册服务,服务名: %s,服务地址: %s \n", srvName, srvAddr)
        em.AddEndpoint(context.TODO(), fmt.Sprintf("%v/%v", srvName, srvAddr), endpoints.Endpoint{Addr: srvAddr}, clientv3.WithLease(lease.ID))
        if err != nil {
            log.Printf("注册服务失败! \n")
            return err
        }
        log.Printf("注册服务成功! \n")
        log.Printf("开始服务定期续租! \n")
        leaseChan, err := etcdRegister.cli.KeepAlive(context.TODO(), etcdRegister.leaseID)
        if err != nil {
            log.Printf("服务定期续租失败! \n")
            return err
        }
        etcdRegister.leaseChan = leaseChan
        log.Printf("服务定期续租成功! \n")
        return nil
    }
    复制代码

    3、提供服务(需要用到ProtoBuf)

    func init() {
        pb.RegisterUserServiceServer(server.GrpcServer, &UserService{})
    }

    2、服务发现

    1、服务发现

    复制代码
    func (etcdDiscovery *etcdDiscovery) Discovery(srvName string) (*grpc.ClientConn, error) {
        target := fmt.Sprintf("etcd:///%s", srvName)
        conn, err := grpc.Dial(target, grpc.WithResolvers(etcdDiscovery.resolver), grpc.WithInsecure())
        if err != nil {
            log.Printf("%s服务发现失败,原因是: %v \n", srvName, err)
            return nil, err
        }
        return conn, nil
    }
    复制代码

    2、调用服务方法(需要用到ProtoBuf)

    复制代码
    func UserRegister(ginCtx *gin.Context) {
        etcdDiscovery := serviceDiscovery.EtcdCenter
        //获取用户服务
        conn, _ := etcdDiscovery.Discovery("study-user-service")
        userService := pb.NewUserServiceClient(conn)
        data, err := userService.SayHello(ginCtx, &pb.Request{})
        if err != nil {
            log.Printf("调用用户服务出错了,原因是: %v \n", err)
        }
        ginCtx.JSON(200, gin.H{
            "message": data,
        })
    }
    复制代码

    备注:api-gateway 和 study-user-service 都使用了空导入的方式,所以主要看空导入的几个 init 函数,main 方法都是空的。

    如果对 Go 的代码执行顺序不熟悉的,可以了解一下!

    参考文献:

    https://etcd.io/docs/v3.5/dev-guide/grpc_naming/

    https://grpc.io/docs/languages/go/basics/

    https://gin-gonic.com/zh-cn/docs/quickstart/

    https://doc.oschina.net/grpc?t=60133

    https://devpress.csdn.net/cloud/62f627bac6770329307fc0c9.html

  • 相关阅读:
    Spark VS Flink,大数据该学什么
    MaxKey单点登录认证系统v3.5.10GA发布
    “网站不安全”该如何解决
    PHP实现输入一年里的第N周求第N周的日期范围
    QT windows与linux之间sokcet通信中文乱码问题解决方法
    macos知名的清理软件 cleanmymac和腾讯柠檬哪个好 cleanmymacx有必要买吗
    使用Vue3在浏览器端进行zip文件压缩
    SQL语句的约束 总结
    实现Springcloud跨项目相互调用(简易版)
    Android Camera App启动流程解析
  • 原文地址:https://www.cnblogs.com/M-Anonymous/p/17159371.html