当前位置: 首页 > article >正文

go-zero学习笔记(四)

在api中访问rpc服务

  1. 必备条件
    api端(客户端)有rpc端的pb文件,以及客户端文件(非必要),且已知rpc端的服务注册方式(etcd、k8s)及地址,端口等
    在这里插入图片描述

  2. api端配置文件编写

    # 新增如下配置:
    # 如果rpc端的服务注册为ETCD
    DemoRpcConf:
      Etcd:
        Hosts:
          - 0.0.0.0:2379 # etcd的地址及端口
        key: demo.rpc #rpc注册时的key
    
    # 如果rpc端的服务注册为K8S
    DemoRpcConf:
      Target: kubernetes:///<service-name>.<namespace>.svc.cluster.local:port
    

    当然还有其他方式,但主要以这两种为主

  3. api端internal/config/config.go编写

    // 在config结构体中新增如下代码:
    DemoRpcConf zrpc.RpcClientConf 
    
  4. api端internal/svc/servicecontext.go编写

    // 在ServiceContext结构体中新增如下代码:
    DemoRpc         demo.DemoClient
    
    // 在NewServiceContext方法的返回值中新增如下代码:
    DemoRpc: democlient.NewDemo(zrpc.MustNewClient(c.DemoRpcConf)),//如果你有democlient包
    DemoRpc: demo.NewDemoClient(zrpc.MustNewClient(c.DemoRpcConf).Conn()), // 只有pb文件
    

    这里,如果你的rpc服务做了多节点部署,zrpc会自动实现基于p2c的负载均衡算法,使客户端到服务端的访问变为负载均衡模式。

  5. rpc方法调用
    经过上述步骤,已经实现rpc客户端的初始化,并将其保存在svc中,那么在logic中,你就可以直接调用具体方法了。
    在这里插入图片描述

本地测试rpc服务

  1. 前提
    如果你在写完rpc的logic层以后,想做一个简单的测试,且你电脑上也没有安装ETCD、k8s等服务注册、服务发现组件,那么此时你可以使用直连的方式。

  2. 在rpc的配置文件中etc/demo.yaml删除关于etcd的配置

    Name: demo.rpc
    ListenOn: 0.0.0.0:8080
    Etcd:
      Hosts:
      - 127.0.0.1:2379
      Key: demo.rpc
    
  3. 直连代码

    package main
    
    import (
    	"context"
    	"demo/rpc/demo"
    	"fmt"
    	"google.golang.org/grpc"
    	"google.golang.org/grpc/credentials/insecure"
    	"google.golang.org/grpc/metadata"
    )
    
    func main() {
    	addr := ":8080" // rpc端口
    
    	conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
    	if err != nil {
    		// 错误处理
    		fmt.Println(err.Error())
    	}
    	defer conn.Close()
    
    	client := demo.NewDemoClient(conn)
    
    	ctx := metadata.AppendToOutgoingContext(context.Background(), "key", "value")
    	resp, err := client.Search(ctx, nil) // 具体方法
    	if err != nil {
    		fmt.Println(err)
    		return
    	}
    	fmt.Printf("==============%#v==============", resp.Projects)
    }
    
    

api请求rpc时使用ctx传值

  1. 需求:
    在上述代码中,api调用rpc时需要传入上下文ctx,有时候,我们需要将一些固定的值由ctx带入,而不是在请求参数中带过去,比如api版本,请求唯一ID等。

  2. 问题:
    如果你使用的是:

    ctx := context.WithValue(r.Context(), "key", "value")
    

    你会发现,在rpc端是无法读取到对应的数据的,也就是说这种方式是无法将值存储在ctx中传递给rpc服务端的。

  3. 解决方案:使用metadata包实现

    // 客户端(api端)实现如下方法设置ctx:
    ctx := metadata.AppendToOutgoingContext(context.Background(), "key", "value")
    // 也可以使用,但是NewOutgoingContext会将之前的数据覆盖,因此推荐第一种
    md := metadata.New(map[string]string{"key": "value", "key1": "value1"})
    ctx := metadata.NewOutgoingContext(context.Background(), md)
    
    // 服务端(rpc端)读取ctx
    md, ok := metadata.FromIncomingContext(l.ctx)
    if ok {
    	for k, v := range md {
    		fmt.Printf("key:%s  value:%s\n", k, v)
    	}
    }
    

更多metadata包使用详情可参考 写给go开发者的gRPC教程-metadata


http://www.kler.cn/a/534514.html

相关文章:

  • 【3】高并发导出场景下,服务器性能瓶颈优化方案-文件压缩
  • 【React】合成事件语法
  • 【Uniapp-Vue3】z-paging插件组件实现触底和下拉加载数据
  • 讯飞智作 AI 配音技术浅析(四):语音特征提取与建模
  • Immutable设计 SimpleDateFormat DateTimeFormatter
  • 车载软件架构 --- 基于AUTOSAR软件架构的ECU开发流程小白篇
  • python(自学10-2)获取豆瓣页面 下载成json格式
  • 7.PPT:“中国梦”学习实践活动【20】
  • MySQL常见的存储引擎和区别
  • ASP.NET Core与EF Core的集成
  • 系留无人机通信中继、空地组网技术详解
  • Spring ApplicationContext接口及其实现类的作用
  • React中为每个列表项显示多个DOM节点的解决方案
  • GS论文阅读--Mini-Splatting
  • vscode+Cmake配置c++轻量级环境
  • Java进阶13 线程池
  • Racecar Gym 代码
  • 深入解析:如何利用 Python 爬虫获取商品销量详情
  • 系统学习算法:专题九 穷举vs暴搜vs深搜vs回溯vs剪枝
  • 畅游Diffusion数字人(15):详细解读字节跳动最新论文——音频+姿态控制人类视频生成OmniHuman-1
  • Vue WebSocket简单应用 ws
  • openEuler系统添加静态路由的方法
  • 【华为OD-E卷 - 114 找最小数 100分(python、java、c++、js、c)】
  • 算法日记11:SC63(离散化)
  • 106,【6】 buuctf web [SUCTF 2019]CheckIn
  • Unity-向量运算及归一化