2

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

 1 year ago
source link: https://www.cnblogs.com/M-Anonymous/p/17159371.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一、标准的项目结构

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

1321357-20230227131927591-1613061519.png
1321357-20230227132142528-114052445.png

1321357-20230227132214075-2061959924.png

1321357-20230227132345714-1128286981.png
1321357-20230227132406885-164019917.png
1321357-20230227132432953-173251348.png
1321357-20230227132516821-1802712165.png
1321357-20230227132552320-797650602.png

 

1321357-20230227132805960-1842997918.png

 

1321357-20230227132839366-683422805.png

二、服务注册与发现流程

1321357-20230227135335048-1816556569.png

 三、示例代码

项目地址:gRPC-GoWeb

1、服务注册

服务注册和发现都可参考 etcd官网 的注册和发现流程,以下是项目的几个步骤的代码,详细的可下载项目查看。

 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、调用服务方法

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://gin-gonic.com/zh-cn/docs/quickstart/

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

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK