贯穿服务的全局配置
2025/7/10大约 5 分钟
贯穿服务的全局配置
概述
GlobalConfiguration
类是网关服务的核心配置中心,负责加载应用配置、管理关键资源、执行服务初始化以及启动网络服务。该类作为整个网关服务的配置中枢,确保服务在启动时能够正确初始化并完成必要的准备工作。
读取配置
网关服务通过Spring Boot的配置文件(如application.yml)进行配置。
在配置文件配置属性:
spring:
application:
name: api-gateway-core # 应用名称,用于服务注册与发现
data:
redis: # Redis数据库配置(用于存储接口信息)
database: 0 # Redis数据库索引(0-15)
host: localhost # Redis服务器地址
port: 6379 # Redis服务器端口
# API网关核心配置
api-gateway:
netty-port: 8888 # Netty服务监听端口
gateway-center: 127.0.0.1:18080 # 网关中心地址(用于配置同步)
group-key: test-key # 网关分组标识(用于启动时获取配置)
weight: 1 # 网关权重(1-100,用于负载均衡)
max-cache: 1000 # 连接对象本地缓存最大数量
boss-threads: 1 # Netty boss线程数(接收连接)
worker-threads: 4 # Netty worker线程数(处理连接)
# Dubbo配置
dubbo:
application:
qos-enable: false # 是否启用Dubbo QOS服务(运维命令)
配置类通过@ConfigurationProperties
注解实现配置绑定,在配置类中配置:
@Data
@Component
@Slf4j
@ConfigurationProperties(prefix = "api-gateway")
public class GlobalConfiguration {
/**
* Netty服务端口
*/
private Integer nettyPort;
/**
* 网关中心地址
*/
private String gatewayCenter;
/**
* 分组Key
*/
private String groupKey;
/**
* 服务权重
*/
private Integer weight;
/**
* 最大缓存数量
*/
private Integer maxCache;
/**
* Netty boss线程数
*/
private Integer bossThreads;
/**
* Netty worker线程数
*/
private Integer workerThreads;
}
复用HTTP和Dubbo连接
/**
* HTTP客户端
*/
private CloseableHttpClient httpClient;
/**
* Dubbo服务缓存
*/
private ConcurrentHashMap<String, GenericService> dubboServiceMap = new ConcurrentHashMap<>();
在
init
方法中对其进行初始化
/**
* 初始化方法
*/
@PostConstruct
public void init() {
log.info("开始初始化全局配置");
this.httpStatementMap = CacheUtil.newLRUCache(maxCache);
log.debug("创建HTTP声明缓存,容量: {}", maxCache);
this.serverName = register();
log.info("服务注册完成,服务名称: {}", serverName);
createHTTPClient();
log.info("HTTP客户端初始化完成");
}
/**
* 创建HTTP客户端连接池
*/
private void createHTTPClient() {
log.debug("创建HTTP连接池");
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(500);
cm.setDefaultMaxPerRoute(50);
cm.setValidateAfterInactivity(30_000);
httpClient = HttpClients.custom()
.setConnectionManager(cm)
.build();
log.debug("HTTP连接池创建成功,最大连接数: 500,单路由最大连接数: 50");
startConnectionEvictor(cm);
}
/**
* 启动连接回收线程
* @param cm 连接管理器
*/
private void startConnectionEvictor(PoolingHttpClientConnectionManager cm) {
log.debug("启动HTTP连接回收线程");
Executors.newSingleThreadScheduledExecutor().scheduleAtFixedRate(() -> {
cm.closeExpiredConnections();
cm.closeIdleConnections(30, TimeUnit.SECONDS);
log.trace("HTTP连接池清理完成");
}, 30, 30, TimeUnit.SECONDS);
}
}
管理接口信息缓存
网关在处理高并发请求时,连接资源的创建和销毁会成为性能瓶颈。GlobalConfiguration
通过httpStatementMap
实现了高效的连接管理,具体可查看缓存详细文档
执行服务初始化代码
由于项目需要在启动时对服务进行上报和获得当前服务名,所以在全局配置类这里需要执行初始化代码
/**
* 向网关中心注册服务
* @return 注册成功的服务名称
* @throws Error 当注册失败时抛出
*/
private String register() {
log.info("开始向网关中心注册服务");
String addr = this.gatewayCenter;
String fullUrl = addr + "/gateway-group-detail/register";
HttpRequest request = HttpUtil.createRequest(cn.hutool.http.Method.POST, fullUrl);
request.header("Content-Type", "application/json");
GroupRegisterReqVO registerVO = new GroupRegisterReqVO();
registerVO.setGroupKey(this.groupKey);
registerVO.setDetailName(environment.getProperty("spring.application.name", "api-gateway-core"));
String localIp = "localhost";
try {
localIp = InetAddress.getLocalHost().getHostAddress();
log.debug("获取本地IP地址: {}", localIp);
} catch (Exception e) {
log.warn("获取本地IP失败,使用默认localhost");
}
registerVO.setDetailAddress(localIp + ":" + nettyPort);
registerVO.setDetailWeight(this.weight);
log.debug("注册请求参数: {}", registerVO);
request.body(JSON.toJSONString(registerVO));
try {
HttpResponse response = request.execute();
String body = response.body();
log.debug("注册响应: {}", body);
String result = JSON.parseObject(body).getString("data");
GroupDetailRegisterRespVO respVO = JSON.parseObject(result, GroupDetailRegisterRespVO.class);
if (StrUtil.isNotBlank(result)) {
log.info("服务注册成功,服务名称: {}", respVO.getServerName());
}
this.safeKey = respVO.getSafeKey();
this.safeSecret = respVO.getSafeSecret();
log.debug("获取安全凭证: key={}", safeKey);
return respVO.getServerName();
} catch (Exception e) {
log.error("服务注册失败,URL: {}, 错误: {}", fullUrl, e.getMessage());
throw new Error("服务注册失败");
}
}
启动Netty服务
在项目启动时使用配置类的部分属性:
@PostConstruct
public void init() {
log.info("开始初始化全局配置");
this.httpStatementMap = CacheUtil.newLRUCache(maxCache);
log.debug("创建HTTP声明缓存,容量: {}", maxCache);
this.serverName = register();
log.info("服务注册完成,服务名称: {}", serverName);
createHTTPClient();
log.info("HTTP客户端初始化完成");
}
这是启动类
/**
* Netty Socket服务端启动类
* 负责初始化并启动Netty服务器
*/
@Slf4j
@Component
public class SocketServerBootStrap {
@Resource
private ServerHandlerInitializer serverHandlerInitializer;
@Resource
private GlobalConfiguration config;
private EventLoopGroup boss;
private EventLoopGroup work;
/**
* 初始化事件循环组
* @param bossThreads 主线程数
* @param workThreads 工作线程数
*/
private void initEventLoopGroup(Integer bossThreads, Integer workThreads) {
log.info("初始化Netty事件循环组,boss线程数: {}, work线程数: {}", bossThreads, workThreads);
this.boss = new NioEventLoopGroup(bossThreads);
this.work = new NioEventLoopGroup(workThreads);
}
/**
* 初始化方法,在Spring容器启动后自动调用
*/
@PostConstruct
public void init() {
log.info("开始启动Netty服务器...");
Channel channel = this.start(config.getNettyPort(), config.getBossThreads(), config.getWorkerThreads());
if (channel == null) {
log.error("Netty服务器启动失败");
throw new RuntimeException("服务启动失败");
}
log.info("Netty服务器启动成功,监听端口: {}", config.getNettyPort());
}
/**
* 启动Netty服务器
* @param nettyPort 监听端口
* @param bossThreads 主线程数
* @param workThreads 工作线程数
* @return 绑定的Channel对象
*/
public Channel start(Integer nettyPort, Integer bossThreads, Integer workThreads) {
log.debug("准备启动Netty服务器,端口: {}, boss线程: {}, work线程: {}",
nettyPort, bossThreads, workThreads);
// 初始化线程组
initEventLoopGroup(bossThreads, workThreads);
try {
log.debug("配置ServerBootstrap参数...");
ServerBootstrap b = new ServerBootstrap();
b.group(boss, work)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128) // 连接队列大小
.childHandler(serverHandlerInitializer); // 设置处理器初始化器
log.info("开始绑定端口: {}...", nettyPort);
Channel channel = b.bind(nettyPort).sync().channel();
log.info("端口绑定成功: {}", nettyPort);
return channel;
} catch (Exception e) {
log.error("网关服务启动失败,端口: {}", nettyPort, e);
// 关闭线程组
if (boss != null) {
boss.shutdownGracefully();
}
if (work != null) {
work.shutdownGracefully();
}
}
return null;
}
}
这是启动加载器
/**
* 服务端初始化器
*/
@Component
public class ServerHandlerInitializer extends ChannelInitializer<SocketChannel> {
@Resource
private AuthorizationHandler authorizationHandler;
@Resource
private PreExecutorHandler preExecutorHandler;
@Resource
private ExecutorHandler executorHandler;
@Resource
private PostExecutorHandler postExecutorHandler;
@Resource
private ResultHandler resultHandler;
@Override
protected void initChannel(SocketChannel channel) {
ChannelPipeline line = channel.pipeline();
line.addLast(new HttpRequestDecoder());
line.addLast(new HttpResponseEncoder());
line.addLast(new HttpObjectAggregator(1024 * 1024 * 10));
line.addLast(authorizationHandler);
line.addLast(preExecutorHandler);
line.addLast(executorHandler);
line.addLast(postExecutorHandler);
line.addLast(resultHandler);
}
}
处理器链说明:
AuthorizationHandler
:验证请求安全凭证PreExecutorHandler
:执行请求前的自定义逻辑(限流、黑白名单等)ExecutorHandler
:核心业务处理(路由转发,泛化调用等)PostExecutorHandler
:响应后处理(日志记录、结果分析等)ResultHandler
:最终响应结果组装