十五章 服务配置拉取和组件使用验证

结合13章组件的开发与14章数据结构的提供,在第15章中重构网关助手组件服务,并把组件引入到 SpringBoot 中使用。

设计

15-设计

结合着第13章,网关算力的助手组件初步实现,本章需要进行扩展以及验证使用。

在本章需要完成从第14章中提供的网关聚合配置信息,拉取到网关算力中,打通这部分的接口调用。后续章节再处理映射操作,因为映射还需要把网关核心算力引入到助手组件中进行包装使用。

在本章除了开发新的组件助手功能外,还需要完成测试工程的使用。

另外对于从注册中心调用的接口,还需要做一些包装处理,方便统一管理。

实现

15-实现

service 包拆分到 domain 领域层,把所需的服务处理都封装到这里来提供服务。这样拆分后,以后只要看这部分代码,就知道domain 就是处理服务的,不用在乱找了。

RegisterGatewayService 网关注册服务

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
package cn.ray.gateway.assist.domain.service;

import cn.hutool.http.HttpUtil;
import cn.ray.gateway.assist.GatewayException;
import cn.ray.gateway.assist.common.Result;
import cn.ray.gateway.assist.domain.model.aggregates.ApplicationSystemRichInfo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
* @author Ray
* @date 2023/5/25 10:18
* @description 网关注册服务
*/
public class RegisterGatewayService {

private Logger logger = LoggerFactory.getLogger(RegisterGatewayService.class);

public void doRegister(String address, String groupId, String gatewayId, String gatewayName, String gatewayAddress) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("groupId", groupId);
paramMap.put("gatewayId", gatewayId);
paramMap.put("gatewayName", gatewayName);
paramMap.put("gatewayAddress", gatewayAddress);
String resultStr = HttpUtil.post(address + "/wg/admin/config/registerGateway", paramMap, 2000);
Result<Boolean> result = JSON.parseObject(resultStr, new TypeReference<Result<Boolean>>(){});
logger.info("向网关中心注册网关算力服务 gatewayId:{} gatewayName:{} gatewayAddress:{} 注册结果:{}", gatewayId, gatewayName, gatewayAddress, resultStr);
if (!"0000".equals(result.getCode()))
throw new GatewayException("网关服务注册异常 [gatewayId:" + gatewayId + "] 、[gatewayAddress:" + gatewayAddress + "]");
}

public ApplicationSystemRichInfo pullApplicationSystemRichInfo(String address, String gatewayId) {
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("gatewayId", gatewayId);
String resultStr = HttpUtil.post(address + "/wg/admin/config/queryApplicationSystemRichInfo", paramMap, 2000);
Result<ApplicationSystemRichInfo> result = JSON.parseObject(resultStr, new TypeReference<Result<ApplicationSystemRichInfo>>(){});
logger.info("从网关中心拉取应用服务和接口的配置信息到本地完成注册。gatewayId:{}", gatewayId);
if (!"0000".equals(result.getCode()))
throw new GatewayException("从网关中心拉取应用服务和接口的配置信息到本地完成注册异常 [gatewayId:" + gatewayId + "]");
return result.getData();
}
}

在domain 模块下,service 包下的实现类中,有这么2个接口;一个是注册网关信息,另外一个是拉取配置服务。

这里是用的 HTTP 因为不希望引入太多的通信模型,后期可以使用策略模式把MQ、Socket 等通信方式引入进来,让系统可以通过多种通信模型与网关中心进行通信。

GatewayAssistantApplication 服务使用

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
package cn.ray.gateway.assist.applicaton;

import cn.ray.gateway.assist.config.GatewayServiceProperties;
import cn.ray.gateway.assist.domain.model.aggregates.ApplicationSystemRichInfo;
import cn.ray.gateway.assist.domain.service.RegisterGatewayService;
import com.alibaba.fastjson.JSON;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

/**
* @author Ray
* @date 2023/5/25 10:11
* @description 网关应用 与 Spring 链接,调用网关注册和接口拉取
*/
public class GatewayAssistantApplication implements ApplicationListener<ContextRefreshedEvent> {

private GatewayServiceProperties properties;
private RegisterGatewayService registerGatewayService;

public GatewayAssistantApplication(GatewayServiceProperties properties, RegisterGatewayService registerGatewayService) {
this.properties = properties;
this.registerGatewayService = registerGatewayService;
}

@Override
public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
// 1. 注册网关服务;每一个用于转换 HTTP 协议泛化调用到 RPC 接口的网关都是一个算力,这些算力需要注册网关配置中心
registerGatewayService.doRegister(properties.getAddress(),
properties.getGroupId(),
properties.getGatewayId(),
properties.getGatewayName(),
properties.getGatewayAddress());

// 2. 拉取网关配置;每个网关算力都会在注册中心分配上需要映射的RPC服务信息,包括;系统、接口、方法
ApplicationSystemRichInfo applicationSystemRichInfo = registerGatewayService.pullApplicationSystemRichInfo(properties.getAddress(), properties.getGatewayId());
System.out.println(JSON.toJSONString(applicationSystemRichInfo));
}
}

这是上一章中我们实现的 Spring 接口 ApplicationListener 在 onApplicationEvent 方法中添加的实现内容。
本章相当于添加了一个额外的扩展调用,之后继续完成调用后的注册映射处理。HTTP => RPC

测试

  1. 新增加 api-gateway-assist-test 的测试工程,它是一个 SpringBoot 的应用工程,用于测试 api-gateway-assist 组件实现。

  2. 注意这个工程的 pom 配置中需要引入 api-gateway-assist

    1
    2
    3
    4
    5
    <dependency>
    <groupId>cn.ray.gateway</groupId>
    <artifactId>api-gateway-assist-02</artifactId>
    <version>1.0-SNAPSHOT</version>
    </dependency>
  3. 在 api-gateway-assist-test 的 applicaton.yml 文件中添加网关配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    server:
    port: 8002

    api-gateway:
    address: http://localhost:80 # 注册中心:从这里获取接口信息以及完成注册网关操作
    groupId: 10001 # 网关分组:每一个网关通信组件都分配一个对应的分组
    gatewayId: api-gateway-g4 # 网关标识
    gatewayName: 电商配送网关 # 网关名称
    gatewayAddress: 127.0.0.1:7399 # 网关服务:网关的通信服务Netty启动时使用IP和端口

测试结果

Center

15-测试-1

assist-test

15-测试-2

思考

  • 这里的注册网关指的是:注册对应的 Netty 通信组件,也就是 api-gateway-core。将其名称、IP端口等信息持久化插入到数据库中的 gateway_server_detail 表中。方便后续与 RPC 服务映射。

gateway_server

15-思考-1

gateway_server_detail

15-思考-2

  • 这里的拉取配置指的是查询对应通信组件 core 下的所管理的 RPC 应用信息,包括接口方法等。共有三种表表示。

application_system

15-思考-3

application_interface

15-思考-4

application_inferface_method

15-思考-5

  • 而通信组件 core 与 RPC 服务信息之间用一个中间表 application_attribution 联系起来。

application_attribution

15-思考-6