Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >腾讯 tRPC-Go 教学——(3)微服务间调用

腾讯 tRPC-Go 教学——(3)微服务间调用

原创
作者头像
amc
修改于 2025-04-18 11:36:07
修改于 2025-04-18 11:36:07
1.4K0
举报
文章被收录于专栏:后台全栈之路后台全栈之路

前两篇文章(12),我构建了一个简单的 HTTP 服务。 HTTP 服务是前后端分离架构中,后端最靠近前端的业务服务。不过纯后台 RPC 之间,出于效率、性能、韵味等等考虑,HTTP 不是我们的首选。本文我们就来看看腾讯是怎么使用 tRPG-Go 构建后台微服务集群的。

本文我们将开始涉及 tRPC 的核心关键点之一:

  • tRPC 服务之间如何互相调用

系列文章

制订协议

与 HTTP 一样,我们还是先制订协议。我们先简单设计一下我们要做的一个服务吧:

  1. 一个前端 HTTP 服务,对接前端
    • 提供一个登录接口, 用于用户名密码(哈希)登录,如果登录成功,给前端返回一个 JWT token,作为身份验证票据
    • JWT token 的生成逻辑在该服务中实现
  2. 一个后端服务, 内部调用,提供用户及认证功能
    • 本文中这个服务实际实现用户名密码验证的功能。

HTTP 服务协议

HTTP 协议比较简单,参照之前的文章格式,我们这么定义

代码语言:proto
AI代码解释
复制
import "common/metadata.proto";

message LoginRequest {
    common.Metadata metadata = 1;
    string username      = 2;
    string password_hash = 3;
}

message LoginResponse {
    int32  err_code = 1;
    string err_msg  = 2;
    Data   data     = 3;

    message Data {
        string id_ticket = 1;
    }
}

// Auth 提供 HTTP 认证接口
service Auth {
    rpc Login(LoginRequest) returns (LoginResponse); // @alias=/demo/auth/Login
}

这里我使用到了 protoc 的跨目录 import 特性。这就需要在 trpc create 命令中追加参数指定 import 的搜索路径。各位可以看一下我的 Makefile 中的 pb 规则:

代码语言:makefile
AI代码解释
复制
.PHONY: $(PB_DIR_TGTS)
$(PB_DIR_TGTS):
	@for dir in $(subst _PB,, $@); do \
		echo Now Build proto in directory: $$dir; \
		cd $$dir; rm -rf mock; \
		export PATH=$(PATH); \
		rm -f *.pb.go; rm -f *.trpc.go; \
		find . -name '*.proto' | xargs -I DD \
			trpc create -f --protofile=DD --protocol=trpc --rpconly --nogomod --alias --mock=false --protodir=$(WORK_DIR)/proto; \
		ls *.trpc.go | xargs -I DD mockgen -source=DD -destination=mock/DD -package=mock ; \
		find `pwd` -name '*.pb.go'; \
	done

注意其中最长的那一句

代码语言:makefile
AI代码解释
复制
		find . -name '*.proto' | xargs -I DD \
			trpc create -f --protofile=DD --protocol=trpc --rpconly --nogomod --alias --mock=false --protodir=$(WORK_DIR)/proto; \

这里通过 --protodir 指定了在 protoc 时的 import 搜索目录。

后端服务协议

后端的服务协议,目前我们先针对这个简单的登录功能,设计一个获取用户帐户数据的功能吧:

代码语言:proto
AI代码解释
复制
import "common/metadata.proto";

message GetAccountByUserNameRequest {
    common.Metadata metadata = 1;
    string username = 2;
}

message GetAccountByUserNameResponse {
    int32  err_code = 1;
    string err_msg  = 2;

    string user_id  = 3;
    string username = 4;
    string password_hash = 5;
    int64  create_ts_sec = 6;
}

// User 提供用户信息服务
service User {
    rpc GetAccountByUserName(GetAccountByUserNameRequest) returns (GetAccountByUserNameResponse);
}

逻辑很简单,就是根据用户名称,获取一个用户信息。我们也可以约定一下,如果没有用户信息,那么就在 err_msg 中返回一个错误信息。


逻辑开发

tRPC 服务间调用

还记得前面说到的两个关键点吗?我们先来讲第一个:tRPC 服务间调用

前面我们规划了两个服务,一个主要对外提供 HTTP 接口,直接对接前端;另外一个服务不对前端开放,这种情况下我们可以使用 trpc 协议。这个协议其实与 grpc 非常相似,也使用了 HTTP/2 的各种机制。

这两个服务互相调用的场景下,HTTP(httpauth 服务)是上游主调方,另一个微服务(user 服务)则是下游被调方。作为被调方,服务的撰写方式与我们最早介绍的 tRPC 服务创建没什么差异,因为在 tRPC 框架下,我们撰写服务逻辑的时候可以无需关注编码格式。

作为主调方的服务,如何获取入参、输出出参,在之前的文章中我们已经知道该怎么做了。接下来我们要关注的是如何调用下游。

我们先看看 httpauth 服务的 Login 实现代码 吧。在代码中,我列出了一个最简单的方法:

代码语言:go
AI代码解释
复制
func (authServiceImpl) Login(
	ctx context.Context, req *httpauth.LoginRequest,
) (rsp *httpauth.LoginResponse, err error) {
	rsp = &httpauth.LoginResponse{}
	uReq := &user.GetAccountByUserNameRequest{
		Metadata: req.GetMetadata(),
		Username: req.GetUsername(),
	}
	uRsp, err := user.NewUserClientProxy().GetAccountByUserName(ctx, uReq)
	if err != nil {
		log.ErrorContextf(ctx, "调用 user 服务失败: %v", err)
		return nil, err
	}
	// 用户存在与否
	if uRsp.GetErrCode() != 0 {
		rsp.ErrCode, rsp.ErrMsg = uRsp.GetErrCode(), uRsp.GetErrMsg()
		return
	}

	// 密码检查
	if uRsp.GetPasswordHash() != req.PasswordHash {
		rsp.ErrCode, rsp.ErrMsg = 404, "密码错误"
		return
	}
	return
}

要说明问题的核心代码,就只有一行:

代码语言:go
AI代码解释
复制
	uRsp, err := user.NewUserClientProxy().GetAccountByUserName(ctx, uReq)

什么 client 初始化,通通不需要。如果下游是一个 tRPC 服务,那么我们只需要在使用的时候再 new 就可以了,这个开销非常低。

服务部署

读者读到上一小节肯定会非常疑惑:啊?代码怎么寻址下游服务的?这一小节我就先尝试着初步解答你的问题。

我们还是像最开始我们的 hello world 服务一样,看看这个 httpauth 服务启动时所需的 trpc_go.yaml 文件 吧:

可以看到,除了之前 hello world 服务给出的例子之外,yaml 文件中多了这一项:

代码语言:yaml
AI代码解释
复制
client:
  service:
    - name: demo.account.User
      target: ip://127.0.0.1:8002
      network: tcp
      protocol: trpc
      timeout: 1000

这一部份规定了在服务中的各种 tRPC 下游依赖的寻址方式。跟服务侧一样,我我这里也建议读者参照 pb 中定义的服务名来给 name 字段赋值(demo.account.User)。

protocol 字段的值是 trpc,这表示我们使用 trpc 协议来调用下游。这一点我们需要与下游协商好,因为即便同是 tRPC 服务,如果 server 和 client 侧没有指定好相同的 protocol 字段,那么双方的通信将会失败。

相比起 server 的配置有 portnicport 等字段,client 并没有这些,取而代之的是一个 target 字段。目前的例子中,配置的值为:ip://127.0.0.1:8002。这个配置包含两部份,也就是 ip://127.0.0.1:8002

其中前面的 ip 表示告诉 tRPC 框架,client 将使用一个被注册为叫做 ip 的寻址器(在 tRPC 中称作 “selector”),寻址器的参数是 127.0.0.1:8002ip 是 tRPC 内置的寻址器,逻辑也很简单,根据后面的 IP + 端口进行寻址。此外,tRPC 还支持 dns 寻址,在这个寻址器下,如果 port 部份是 443,并且 protocol 为 http,那么tRPC 会自动使用 https 调用。

当然,在正式生产环境下,我们的服务间很少直接使用 ip 寻址器进行服务发现。在后文我会介绍一下我们实际使用的 “北极星” 名字服务系统。此处读者先知道寻址器功能即可,咱们先把服务打通,然后再来讲更进阶的事情。


下一步

本文我们说明了从一个 tRPC 服务,如何调用另一个 tRPC 服务。下一篇文章我们从那个被调用的 tRPC 服务来介绍,如何把诸如 MySQLRedisKafka 等组件也接入 tRPC 框架中。


本文章采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

原作者: amc,欢迎转载,但请注明出处。

原文标题:《手把手 tRPC-Go 教学——(3)微服务间调用》

发布日期:2024-01-29

原文链接:https://cloud.tencent.com/developer/article/2384591

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
腾讯 tRPC-Go 教学——(5)filter、context 和日志组件
本文咱们来介绍一下在 tRPC 中的 filter 机制、context 用法,以及在相关机制上可以实现的 tracing log 能力。
amc
2024/03/04
1.2K0
腾讯 tRPC-Go 教学——(5)filter、context 和日志组件
腾讯 tRPC-Go 教学——(1)搭建服务
2023 年底腾讯统一的 RPC 框架 tRPC 正式开源。遍观全网,似乎大部份是对 tRPC 概念上的宣传、架构上的设计,而如何开发、如何部署的文章凤毛麟角。于是笔者小试牛刀撰此文,或许会成为一系列,希望能抛砖引玉。
amc
2024/01/14
2.8K2
腾讯 tRPC-Go 教学——(1)搭建服务
腾讯 tRPC-Go 教学——(4)tRPC 组件生态和使用
之前我花了三篇文章来介绍 tRPC 怎么用。而 tRPC 给开发者带来的便利, 在整整三篇文章中,我也只是介绍了它可以方便服务在 HTTP、trpc、grpc 三种协议之间灵活切换。诚然, tRPC 作为能够统一腾讯内开发框架的一个生态级产品,它的能力显然不止这些。这一篇文章,咱们来一起初窥 tRPC 的周边生态有哪些, 以及其中的第三方组件使用方法。
amc
2024/02/06
1.8K6
腾讯 tRPC-Go 教学——(4)tRPC 组件生态和使用
腾讯 tRPC-Go 教学——(6)服务发现
本文我们来讲一讲对于微服务架构来说,最重要的一个点了:服务发现及其对应的名字服务功能。
amc
2024/05/01
1.1K0
腾讯 tRPC-Go 教学——(6)服务发现
腾讯 tRPC-Go 教学——(2)trpc HTTP 能力
上一篇文章 中我们快速搭建了一个 http API 服务,并且我们可以看到,对外提供了 URL query 和 application/json 两种服务模式。那么实际上,我们到底实现了什么、并且能够做些什么?读者可能还是没有直观的感受,因此必要先来简单 review 一下。就让我们先放下敲代码的小手,一起看看刚刚写出来的都是些什么玩意儿吧。
amc
2024/01/16
1.8K0
腾讯 tRPC-Go 教学——(2)trpc HTTP 能力
腾讯 tRPC-Go 教学——(7)服务配置和指标上报
配置,是一个服务的重要组成部份。一般来说,业务的逻辑写在代码中,而与系统架构、运维等等偏运维的功能,通过配置来处理。tRPC 框架的配置,可以分为两类:冷配置和热配置。
amc
2024/05/19
1.2K8
腾讯 tRPC-Go 教学——(7)服务配置和指标上报
腾讯 tRPC-Go 教学——(8)通过泛 HTTP 能力实现和观测 MCP 服务
最近 MCP 大火,其实 tRPC 也可以提供泛 HTTP 接入的能力。内网其实已经对 mcp-go 进行了封装并支持,但是相关代码还没有同步到开源版上。
amc
2025/04/18
5200
腾讯 tRPC-Go 教学——(8)通过泛 HTTP 能力实现和观测 MCP 服务
逆微服务潮流?基于腾讯 tRPC-Go 单体化改造怎么节省上万核 CPU
微服务架构一直以来是服务治理的基本盘之一,落地到云原生上,往往是每个 K8s pods 部署一个服务,独立迭代、独立运维。
amc
2023/11/07
1.6K0
逆微服务潮流?基于腾讯 tRPC-Go 单体化改造怎么节省上万核 CPU
tRPC初探,开源RPC框架新成员
在最近的技术探索中,我触到了一个全新的开源RPC框架——tRPC。这个新框架给我留下了深刻的印象,我想借此机会分享一下我的初体验和一些观察。
闫同学
2023/12/03
4.7K2
grpc实践-学会grpc就是这么简单
hello,我是asong,这是我的第七篇原创文章。上一篇我们使用go的标准库rpc进行实践,使用起来还是很方便的,这一篇我们来学习一grpc。
Golang梦工厂
2022/07/07
5020
grpc实践-学会grpc就是这么简单
tRPC-Go 链路透传消息的源码级解读
在分布式链路追踪等场景下,会使用到微服务调用链路上的透传能力,tRPC-Go 基于 tRPC 协议的头部设计实现了对链路透传的支持,这篇文章从源码角度分析链路透传的设计实现,文章中会涉及 tRPC-go 里不同场景中如何正确使用链路透传功能。
Martin Hong
2024/05/14
2070
鹅厂火热开发框架:trpc-go设计理念介绍
作者:ronaldoliu,腾讯 IEG 后台开发工程师 trpc-go 是目前公司运用广泛的一个开发框架,支持多协议扩展,能够一键集成各种公司现有平台的功能,非常方便。那么它到底是怎么做到的呢? trpc-go 是目前公司里非常火热的一个开发框架,集成了很多开箱即用的功能,非常方便。trpc-go 代码量不算太多,但是写得还是有点绕,直接阅读可能会比较晕。因此本文主要对 trpc-go 的模块设计进行一个分享,帮助大家构建一个整体视图,后续有需要再针对性的去阅读各模块源码即可。 做后端开发的同学肯定接触过
腾讯技术工程官方号
2023/01/11
4.8K6
鹅厂火热开发框架:trpc-go设计理念介绍
Golang 语言怎么使用 go-micro 和 gin 开发微服务?
Go Micro 是一个分布式系统开发框架。Go Micro 提供了分布式系统开发的核心需求,包括 RPC 和事件驱动的通信。Gin 是一个用 Golang 编写的 web 框架。本文首先介绍怎么使用 go-micro 和 go-grpc 构建微服务,然后再介绍怎么集成 gin 和 go-micro。我们使用的 go-micro 版本是 v1.18.0,golang 版本是 v1.13,gin 版本是 v1.7.2。
frank.
2021/08/13
3.1K0
Golang 语言怎么使用 go-micro 和 gin 开发微服务?
tRPC智能体生态又升级:发布A2A协议的实现trpc-a2a-go
代码已开源至 GitHub:https://github.com/trpc-group/trpc-a2a-go
腾讯开源
2025/04/20
2930
tRPC智能体生态又升级:发布A2A协议的实现trpc-a2a-go
腾讯 tRPC-Go 框架核心实现源码解读
tRPC 是一套由腾讯开源的高性能、跨多种编程语言、插件化的 RPC 框架。tRPC-Go 是框架在 Golang 编程语言下的官方实现。
Martin Hong
2024/05/14
7790
微服务不香了?单体化改造为我们节省上万核 CPU!
微服务一直以来是服务治理的基本盘之一,落地到云原生上,往往是每个 K8s pods 部署一个服务,独立迭代、独立运维。
腾讯云开发者
2023/11/14
8840
微服务不香了?单体化改造为我们节省上万核 CPU!
Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第一篇(内附开发 demo)
小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识,快速建立小程序内的用户体系。
为少
2021/05/27
1.3K0
Go + gRPC-Gateway(V2) 构建微服务实战系列,小程序登录鉴权服务:第一篇(内附开发 demo)
后台自动化测试与持续部署实践
作者:cloudyzhao,腾讯 PCG 后台开发工程师 随着 DevOps 研发模式思想的普及,“测试左移”、“开发负责质量”等理念也开始深入各业务团队。本文以一个实际项目( LogReplay )的 DevOps 实践为例,介绍如何通过可测性提升、自动化测试、持续集成和持续部署流程,最终实现后台微服务的高质量、持续、自动化部署。 测试左移是 DevOps 研发模式中开发全面负责质量的核心环节之一,而测试左移的一个重要手段,就是在开发过程中的各环节快速执行大量有效的自动化测试用例,从而尽早地发现得到质量
腾讯技术工程官方号
2022/04/19
2K0
后台自动化测试与持续部署实践
trpc代码无缝迁移到grpc框架方案
改造protoc-gen-grpc 代码 支持trpc的协议,插件 protoc-gen-trpc2grpc
lishaohui
2022/07/08
1.7K0
trpc代码无缝迁移到grpc框架方案
Go 微服务框架 go-micro 使用客户端 RPC 调用服务端方法返回 408 怎么解决?
本文我们使用 go-micro 构建微服务的服务端和客户端,并使用 gin 集成客户端构建 HTTP Api,在代码中模拟客户端 RPC 调用服务端方法返回 408 的问题,以及怎么解决?
frank.
2023/09/08
7260
Go 微服务框架 go-micro  使用客户端 RPC 调用服务端方法返回 408 怎么解决?
推荐阅读
相关推荐
腾讯 tRPC-Go 教学——(5)filter、context 和日志组件
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档