# 《高性能Polaris网关》完整实战案例-第02节:网关访问后端服务RPC接口完整案例

作者:冰河
星球:http://m6z.cn/6aeFbs (opens new window)
博客:https://binghe.gitcode.host (opens new window)
文章汇总:https://binghe.gitcode.host/md/all/all.html (opens new window)
源码获取地址:https://t.zsxq.com/0dhvFs5oR (opens new window)

沉淀,成长,突破,帮助他人,成就自我。

  • 本节难度:★★★☆☆
  • 本节重点:实现网关访问后端服务RPC接口的完整实战案例,深入理解高性能Polaris网关访问后端服务的完整流程。重点掌握整体调用链路的设计思路和设计方法,并能够将其灵活应用到自身实际项目中。

设计并实现完网关的主体流程和网关的客户端SDK后,如何检验后端服务能够方便快速的对接网关?如何验证后端服务服务对接网关时,自动将自身服务实例注册到注册中心?又该如何验证网关通过服务发现自动将请求负载均衡路由到后端服务的RPC接口?如何实现网关访问后端RPC接口的完整案例?

专栏已上线,点击学习:https://binghe.gitcode.host/md/project/gateway/start/2024-05-19-start.html (opens new window)

# 一、背景

截止到目前,我们已经完成了网关核心主体功能的设计和开发,包含:通用模型的设计与实现、通用过滤器的设计与实现、通用处理器的设计与实现、核心容器的设计与实现、启动流程的设计与实现、注册中心的设计与实现、负载均衡的设计与实现、增强型负载均衡的设计与实现、配置中心的设计与实现和网关热插拔插件的设计与实现和客户端SDK等。

接下来,我们就要验证设计和实现的高性能Polaris网关是否符合设计的预期,能否通过注册中心的服务注册与发现、配置中心的配置管理、通用模型的数据转换、过滤器链的请求传递、通用处理器的性能增强、核心启动容器的管理、负载均衡的路由设计、热插拔插件的功能增强和网关的异步调用和异步响应等机制完整的实现网关的核心功能。目前,已经实现了网关访问后端服务HTTP接口完整案例,接下来,就实现网关访问后端服务RPC接口的完整案例。

# 二、本节重点

实现网关访问后端服务RPC接口的完整实战案例,深入理解高性能Polaris网关访问后端服务的完整流程。重点掌握整体调用链路的设计思路和设计方法,并能够将其灵活应用到自身实际项目中。

# 三、实战场景

本节,实现网关访问后端服务RPC接口的完整实战案例。

  • 启动网关和后端服务,通过网关访问后端服务RPC接口,正确返回用户信息。
  • 停止后端服务,通过网关访问后端服务RPC接口,返回503:后端服务暂时不可用,请稍后再试
  • 再次启动后端服务,通过网关访问后端服务RPC接口,正确返回用户信息。

# 四、服务规划

实战通过高性能Polaris网关访问后端服务RPC接口的规划如下所示。

服务名 服务说明 端口 接口
polaris-examples-rpc 后端服务 8081 /rpc-server/get-user
高性能Polaris网关 网关服务 10000 访问polaris-examples-rpc的RPC接口用来测试

# 五、案例实现

在整个实战案例实现的过程中,主要分为后端服务整合SDK和配置中心添加服务配置两个大的步骤。

# 5.1 后端服务整合SDK

(1)添加客户端SDK引用

在polaris-examples-rpc工程下的pom.xml文件中添加对网关RPC客户端的引用依赖,如下所示。

<dependencies>
    <dependency>
        <groupId>io.binghe.polaris</groupId>
        <artifactId>polaris-client-rpc</artifactId>
        <version>${project.version}</version>
    </dependency>
    <!--可选的依赖-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>${spring-boot.version}</version>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <version>${spring-boot.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <exclusions>
            <exclusion>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-starter</artifactId>
        <version>${dubbo.version}</version>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-spring-boot-autoconfigure-compatible</artifactId>
        <version>${dubbo.version}</version>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-registry-nacos</artifactId>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo-serialization-kryo</artifactId>
    </dependency>
</dependencies>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

(2)创建实体类

创建User实体类,用于RPC接口测试。

源码详见:polaris-examples-rpc工程下的io.binghe.polaris.examples.rpc.entity.User。

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
    @Serial
    private static final long serialVersionUID = 9166277076798447427L;

    private Long userId;
    private String userName;
}
1
2
3
4
5
6
7
8
9
10

(3)创建接口

创建UserService接口,定义Dubbo接口。

源码详见:polaris-examples-rpc工程下的io.binghe.polaris.examples.rpc.service.UserService。

public interface UserService {
    User getUser(Long userId);
}
1
2
3

(4)创建实现类

创建UserServiceImpl实现类,用于实现UserService接口。

源码详见:polaris-examples-rpc工程下的io.binghe.polaris.examples.rpc.service.impl.UserServiceImpl。

@Slf4j
@Service(timeout = 5000)
@PolarisService(serviceId = "rpc-server", protocol = Protocol.RPC, patternPath = "/rpc-server/**")
public class UserServiceImpl implements UserService {

    @Override
    @PolarisInvoker(ruleId = "rpc-server-rule",path = "/rpc-server/get-user")
    public User getUser(Long userId) {
        User user = new User(userId, "userName_" + userId);
        log.info("生成的User对象为:{}", user);
        return user;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13

UserServiceImpl类是整个案例的实现重点。可以看到,在UserServiceImpl类中,标注了Dubbo的@Service注解,并且设置的超时时间为5s。

同时,在UserServiceImpl类上标注了网关客户端的@PolarisService注解,设置的serviceId为rpc-server,protocol为rpc,匹配的path路径规则为/rpc-server/**。

在getUser()方法上标注了网关客户端的@PolarisInvoker注解,规则id为rpc-server-rule,path路径为/rpc-server/get-user。

也就是说,通过网关访问/rpc-server/get-user接口,就可以访问到UserServiceImpl类的getUser()方法。

这里需要需要的是@PolarisInvoker注解中的ruleId的值,需要与配置中心中某个规则的id相匹配。

(5)实现启动类

实现RpcExampleStarter启动类。

源码详见:polaris-examples-rpc工程下的io.binghe.polaris.examples.rpc.RpcExampleStarter.

@SpringBootApplication
@EnableDubbo
public class RpcExampleStarter {
    public static void main(String[] args) {
        SpringApplication.run(RpcExampleStarter.class, args);
    }
}
1
2
3
4
5
6
7

注意RpcExampleStarter类上的@EnableDubbo注解。

至此,对后端服务整合RPC客户端SDK完成,就是这么简单,添加pom.xml依赖,对接口类添加注解即可。

# 5.2 添加服务配置

这里,以Nacos配置中心为例,在Nacos中添加服务配置。服务配置的DataId为polaris-gateway,Group为dev,配置内容如下:

[
	{
	"id": "rpc-server-rule",
	"name": "RPC测试配置规则",
	"protocol": "rpc",
	"serviceId": "rpc-server",
	"prefix":"/rpc-server",
	"paths": [],
	"filterRules": [
		{
			"id": "loadbalancerFilter",
			"config":"{\"balanceType\" : \"robin\"}"
		},
		{
			"id": "rpcFilter"
		},
		{
			"id": "errorFilter"
		}
	]
  }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

加上之前添加的http配置规则,整体如下所示。

[
  {
	"id": "http-server-rule",
	"name": "HTTP测试配置规则",
	"protocol": "http",
	"serviceId": "http-server",
	"prefix":"/http-server",
	"paths": [],
	"filterRules": [
		{
			"id": "loadbalancerFilter",
			"config":"{\"balanceType\" : \"robin\"}"
		},
		{
			"id": "httpFilter"
		},
		{
			"id": "errorFilter"
		}
	]
  },
	{
	"id": "rpc-server-rule",
	"name": "RPC测试配置规则",
	"protocol": "rpc",
	"serviceId": "rpc-server",
	"prefix":"/rpc-server",
	"paths": [],
	"filterRules": [
		{
			"id": "loadbalancerFilter",
			"config":"{\"balanceType\" : \"robin\"}"
		},
		{
			"id": "rpcFilter"
		},
		{
			"id": "errorFilter"
		}
	]
  }
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

配置后的效果如下所示。


至此,所有准备工作完成。接下来,分别启动后端服务和网关。

# 六、启动服务

# 6.1 启动后端服务

(1)启动polaris-examples-rpc工程

运行polaris-examples-rpc工程的io.binghe.polaris.examples.rpc.RpcExampleStarter启动后端服务。启动成功后会输出如下日志。

启动高性能Polaris网关RPC客户端...
1

(2)查看后端服务注册情况

查看后端服务是否自动注册到Nacos注册中心,如下所示。


可以看到,后端服务已经自动注册到注册中心,服务名称为rpc-server。

至此,后端服务准备就绪。

# 6.2 启动网关

(1)启动polaris-core工程

启动polaris-core工程下的io.binghe.polaris.core.Starter。网关启动成功会输出包含但不限于如下日志。

Polaris网关启动成功,监听端口:10000
从Nacos配置中心获取到的配置为
服务注册:
刷新服务和服务实例:
执行Logger插件的init方法...
1
2
3
4
5

(2)查看服务注册情况

查看网关服务是否自动注册到Nacos注册中心,如下所示。


可以看到,启动网关后也会自动注册到注册中心,网关的服务名称为polaris。

至此,网关准备就绪。

# 七、验证实战场景

这里,就对网关访问后端服务RPC接口的完整案例进行验证。

# 7.1 环境准备

在apifox中,通过网关访问后端服务的接口为:http://localhost:10000/rpc-server/get-user。

在请求头header中添加key为uniqueId的请求头,值为rpc-server:1.0.0。其中,值为后端服务的serviceId:version。也就是服务id:版本号。

另外,也在请求头header中添加key为content-type的请求头,值为application/json。


在body部分传递的参数为[1],如下所示。


之所以body部分传递的是Json数组值,是因为在RPC调用的过程中,底层的核心参数如下:

/**
 * 服务的接口名称
 */
private String interfaceClass;
/**
 * 服务的方法名
 */
private String methodName;
/**
 * 服务的方法参数签名
 */
private String[] parameterTypes;
/**
 * 调用的参数内容
 */
private Object[] args;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

RPC调用实际是通过反射调用方法,参数需要传递数组,所以,在传参上,需要传递一个Json数组值。

# 7.2 同时启动网关和后端服务

同时启动网关和后端服务,通过网关访问后端服务RPC接口,如下所示。


可以看到,同时启动网关和后端服务,通过网关访问后端服务接口,会正常返回用户信息,符合预期效果。

# 7.3 停止后端服务

停止后端服务,通过网关访问后端服务RPC接口,如下所示。


可以看到,停止后端服务,通过网关访问后端服务RPC接口,返回503:后端服务暂时不可用,请稍后再试。

网关也会输出如下日志。

下游服务发生异常,请稍后再试
1

并抛出对应的异常,符合预期效果。

# 7.4 恢复后端服务

再次启动后端服务,通过网关访问后端RPC服务接口,如下所示。


可以看到,再次启动后端服务,通过网关访问后端服务RPC接口,正确返回用户信息。符合预期效果。

# 八、本节总结

本节,主要实战的形式验证了网关访问后端服务RPC接口完整案例,结果都符合预期效果。

希望这节内容能够为大家带来实质性的收获,最后,可以在评论区写下你学完本章节的收获,祝大家都能学有所成,我们一起搞定高性能Polaris网关。

# 九、写在最后

在冰河的知识星球除了目前正在热更的高性能网关和RPC视频外,还有其他9个项目,像DeepSeek大模型、手写高性能熔断组件、手写通用指标上报组件、手写高性能数据库路由组件、分布式IM即时通讯系统、Sekill分布式秒杀系统、手写RPC、简易商城系统等等,这些项目的需求、方案、架构、落地等均来自互联网真实业务场景,让你真正学到互联网大厂的业务与技术落地方案,并将其有效转化为自己的知识储备。

值得一提的是:冰河自研的Polaris高性能网关比某些开源网关项目性能更高,并且冰河也正在为企业级高性能RPC框架录制视频,全程带你分析原理和手撸代码。 你还在等啥?不少小伙伴经过星球硬核技术和项目的历练,早已成功跳槽加薪,实现薪资翻倍,而你,还在原地踏步,抱怨大环境不好。抛弃焦虑和抱怨,我们一起塌下心来沉淀硬核技术和项目,让自己的薪资更上一层楼。


目前,领券加入星球就可以跟冰河一起学习《DeepSeek大模型》、《手写高性能通用熔断组件项目》、《手写高性能通用监控指标上报组件》、《手写高性能数据库路由组件项目》、《手写简易商城脚手架项目》、《手写高性能RPC项目》和《Spring6核心技术与源码解析》、《实战高并发设计模式》、《分布式Seckill秒杀系统》、《分布式IM即时通讯系统》和《手写高性能Polaris网关》,从零开始介绍原理、设计架构、手撸代码。

花很少的钱就能学这么多硬核技术、中间件项目和大厂秒杀系统与分布式IM即时通讯系统,比其他培训机构不知便宜多少倍,硬核多少倍,如果是我,我会买他个十年!

加入要趁早,后续还会随着项目和加入的人数涨价,而且只会涨,不会降,先加入的小伙伴就是赚到。

另外,还有一个限时福利,邀请一个小伙伴加入,冰河就会给一笔 分享有奖 ,有些小伙伴都邀请了50+人,早就回本了!

# 十、其他方式加入星球

  • 链接 :打开链接 http://m6z.cn/6aeFbs 加入星球。
  • 回复 :在公众号 冰河技术 回复 星球 领取优惠券加入星球。

特别提醒: 苹果用户进圈或续费,请加微信 hacker_binghe 扫二维码,或者去公众号 冰河技术 回复 星球 扫二维码加入星球。

好了,今天就到这儿吧,我是冰河,我们下期见~~