代码初始化
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
# CrossModule
|
||||
|
||||
**跨服独立进程**:仅启动 **一个 CmdRpc TCP 服务**(默认 **9200**),处理来源为 **`CommandSource.CROSS_TCP`** 的命令。
|
||||
区服通过 **`CrossTcpClient`**(在 ServerModule)作为 **TCP 客户端** 连到本进程。
|
||||
|
||||
## 进程职责
|
||||
|
||||
| 职责 | 说明 |
|
||||
|------|------|
|
||||
| 监听 TCP | `CrossTcpServer` 在 `ApplicationReadyEvent` 后 `bind(cross.tcp.port)` |
|
||||
| Pipeline | `CrossTcpChannelInitializer`:`LengthPrefixedProtobuf` 解码 + `CmdRpcTcpFrameHandler` |
|
||||
| 命令路由 | `CrossGameCommandRegistry` 只注册 `@Cmd(source=CROSS_TCP)` 的 Bean |
|
||||
| 链路安全(可选) | `CrossLinkAcceptProperties`:`cross.link.expected-token` 非空时校验注册 token |
|
||||
|
||||
## 网络拓扑
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
subgraph Zone["ServerModule"]
|
||||
CC[CrossTcpClient]
|
||||
end
|
||||
subgraph Cross["CrossModule :9200"]
|
||||
XT[CrossTcpServer]
|
||||
PL[pipeline]
|
||||
REG[CrossGameCommandRegistry]
|
||||
end
|
||||
CC <-->|单 TCP 长连接 长度前缀+CmdRpcEnvelope| XT
|
||||
XT --> PL --> REG
|
||||
```
|
||||
|
||||
## 入站 Pipeline(与 BaseModule 一致)
|
||||
|
||||
```text
|
||||
Socket
|
||||
→ LengthFieldBasedFrameDecoder(由 LengthPrefixedProtobuf 配置)
|
||||
→ CmdRpcTcpFrameHandler
|
||||
→ CmdRpcChannelDispatch(linkSource = CROSS_TCP)
|
||||
→ GameCommand.execute
|
||||
→ 编码响应帧写回
|
||||
```
|
||||
|
||||
跨服侧 **`CrossRpcInvoker` 传 `null`**:跨服命令里 **不应** 再同步 `roundTrip` 回调区服(Demo 未实现跨服主动调区服)。
|
||||
|
||||
## 已实现的 `CROSS_TCP` 命令
|
||||
|
||||
### 业务:Service_2 / Method2
|
||||
|
||||
- **`CrossForwardCommand`**(`AbstractTypedPbCommand`)
|
||||
- 入参:`CrossForwardCts`
|
||||
- 出参:`CrossForwardStc`
|
||||
- Demo 逻辑:给 `trace` 加前缀并写入 `cross_time_ms`。
|
||||
|
||||
### 链路:Service_4(注册 / 心跳)
|
||||
|
||||
| method | 命令类 | 作用 |
|
||||
|--------|--------|------|
|
||||
| Register | `CrossLinkRegisterCommand` | 校验 `server_id`、可选 `expected-token` |
|
||||
| Heartbeat | `CrossLinkHeartbeatCommand` | 回显 `client_time_ms`,写入 `cross_time_ms` |
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Z as 区服 CrossTcpClient
|
||||
participant X as CrossModule
|
||||
Z->>X: Service_4 Register + link_seq + CrossLinkRegisterCts
|
||||
X-->>Z: 同 link_seq + CrossLinkRegisterStc(ok/message)
|
||||
loop 每 heartbeat-interval-ms
|
||||
Z->>X: Service_4 Heartbeat + link_seq
|
||||
X-->>Z: CrossLinkHeartbeatStc
|
||||
end
|
||||
Z->>X: Service_2 Method2 + link_seq + CrossForwardCts
|
||||
X-->>Z: CrossForwardStc
|
||||
```
|
||||
|
||||
## 配置(`src/main/resources/application.yml`)
|
||||
|
||||
```yaml
|
||||
cross:
|
||||
tcp:
|
||||
port: 9200 # Netty 监听端口
|
||||
link:
|
||||
expected-token: "" # 非空则须与区服 cross.token 一致
|
||||
app:
|
||||
logging:
|
||||
dir: logs/CrossModule
|
||||
```
|
||||
|
||||
## 启动
|
||||
|
||||
主类:`com.huangzj.cross.CrossModuleApplication`
|
||||
|
||||
建议 **先于区服** 启动,否则区服 `CrossTcpClient` 预热与心跳会失败(日志告警),待跨服起来后下次业务或心跳会重连。
|
||||
|
||||
## 日志
|
||||
|
||||
`logback-spring.xml`:控制台 + 按级别分文件(`info.log` / `error.log`),目录由 `app.logging.dir` 指定。
|
||||
|
||||
## 扩展跨服 RPC
|
||||
|
||||
1. 在 **ProtoBufModule** 增加 `service/method` 与消息体。
|
||||
2. 在本模块新增 `@Cmd(source=CROSS_TCP, ...)` 的 `GameCommand` 或 `AbstractTypedPbCommand`。
|
||||
3. 若需强类型自动解码,使用 **`AbstractTypedPbCommand`**;启动时 **`ProtoRegistryAutoConfigurer`** 会为跨服进程注册对应 `ProtoInfo`。
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>huangzj</groupId>
|
||||
<artifactId>comm-framework</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>CrossModule</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>CrossModule</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>huangzj</groupId>
|
||||
<artifactId>ProtoBufModule</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>huangzj</groupId>
|
||||
<artifactId>BaseModule</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>com.huangzj.cross.CrossModuleApplication</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.huangzj.cross;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
|
||||
|
||||
/**
|
||||
* 跨服独立进程:只起 TCP + 命令注册,记得先让它跑起来区服才能 proxy。
|
||||
*/
|
||||
@SpringBootApplication(scanBasePackages = "com.huangzj")
|
||||
@ConfigurationPropertiesScan(basePackages = "com.huangzj")
|
||||
public class CrossModuleApplication {
|
||||
|
||||
/** 轻量进程,一般先于区服启动。 */
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(CrossModuleApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.huangzj.cross.cmd;
|
||||
|
||||
import com.huangzj.base.cmd.AbstractTypedPbCommand;
|
||||
import com.huangzj.base.cmd.Cmd;
|
||||
import com.huangzj.base.cmd.CommandContext;
|
||||
import com.huangzj.base.cmd.CommandSource;
|
||||
import com.huangzj.cmd.gen.CrossForwardCts;
|
||||
import com.huangzj.cmd.gen.CrossForwardStc;
|
||||
import com.huangzj.cmd.gen.PbService;
|
||||
import com.huangzj.cmd.gen.Service2_Method;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/** 跨服示例:{@link PbService#Service_2} + {@link Service2_Method#Method2}。 */
|
||||
@Component
|
||||
@Cmd(
|
||||
source = CommandSource.CROSS_TCP,
|
||||
serviceId = PbService.Service_2_VALUE,
|
||||
methodId = Service2_Method.Method2_VALUE)
|
||||
public class CrossForwardCommand extends AbstractTypedPbCommand<CrossForwardCts, CrossForwardStc.Builder> {
|
||||
|
||||
@Override
|
||||
protected void run(CommandContext ctx, CrossForwardCts cts, CrossForwardStc.Builder stcBuilder) {
|
||||
// Demo:给 trace 加前缀便于区分「跨服加工」;生产可在此落库、转发其它服等
|
||||
stcBuilder.setTrace("cross:" + cts.getTrace()).setCrossTimeMs(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.huangzj.cross.cmd;
|
||||
|
||||
import com.huangzj.base.cmd.CommandSource;
|
||||
import com.huangzj.base.spring.SpringGameCommandRegistry;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 跨服进程只认 {@link CommandSource#CROSS_TCP} 的命令,别的来源不会进这张表。
|
||||
*/
|
||||
@Component
|
||||
public class CrossGameCommandRegistry extends SpringGameCommandRegistry {
|
||||
|
||||
/** 启动时扫 Bean,只收集带 {@code @Cmd(source=CROSS_TCP)} 的实现。 */
|
||||
public CrossGameCommandRegistry(ApplicationContext applicationContext) {
|
||||
super(applicationContext, CommandSource.CROSS_TCP);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.huangzj.cross.cmd;
|
||||
|
||||
import com.huangzj.base.cmd.AbstractTypedPbCommand;
|
||||
import com.huangzj.base.cmd.Cmd;
|
||||
import com.huangzj.base.cmd.CommandContext;
|
||||
import com.huangzj.base.cmd.CommandSource;
|
||||
import com.huangzj.cmd.gen.CrossLinkHeartbeatCts;
|
||||
import com.huangzj.cmd.gen.CrossLinkHeartbeatStc;
|
||||
import com.huangzj.cmd.gen.PbService;
|
||||
import com.huangzj.cmd.gen.Service4_Method;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/** 区服 ↔ 跨服长连接心跳(仅 {@link CommandSource#CROSS_TCP})。 */
|
||||
@Component
|
||||
@Cmd(
|
||||
source = CommandSource.CROSS_TCP,
|
||||
serviceId = PbService.Service_4_VALUE,
|
||||
methodId = Service4_Method.Heartbeat_VALUE)
|
||||
public class CrossLinkHeartbeatCommand extends AbstractTypedPbCommand<CrossLinkHeartbeatCts, CrossLinkHeartbeatStc.Builder> {
|
||||
|
||||
@Override
|
||||
protected void run(CommandContext ctx, CrossLinkHeartbeatCts cts, CrossLinkHeartbeatStc.Builder stcBuilder) {
|
||||
// 原样回显客户端时间,便于区服侧算 RTT;cross_time_ms 为跨服处理时刻
|
||||
stcBuilder.setClientTimeMs(cts.getClientTimeMs()).setCrossTimeMs(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.huangzj.cross.cmd;
|
||||
|
||||
import com.huangzj.base.cmd.AbstractTypedPbCommand;
|
||||
import com.huangzj.base.cmd.Cmd;
|
||||
import com.huangzj.base.cmd.CommandContext;
|
||||
import com.huangzj.base.cmd.CommandSource;
|
||||
import com.huangzj.cmd.gen.CrossLinkRegisterCts;
|
||||
import com.huangzj.cmd.gen.CrossLinkRegisterStc;
|
||||
import com.huangzj.cmd.gen.PbService;
|
||||
import com.huangzj.cmd.gen.Service4_Method;
|
||||
import com.huangzj.cross.config.CrossLinkAcceptProperties;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 区服 TCP 连上跨服后的注册握手(仅 {@link CommandSource#CROSS_TCP})。
|
||||
*/
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Cmd(
|
||||
source = CommandSource.CROSS_TCP,
|
||||
serviceId = PbService.Service_4_VALUE,
|
||||
methodId = Service4_Method.Register_VALUE)
|
||||
public class CrossLinkRegisterCommand extends AbstractTypedPbCommand<CrossLinkRegisterCts, CrossLinkRegisterStc.Builder> {
|
||||
|
||||
private final CrossLinkAcceptProperties acceptProperties;
|
||||
|
||||
@Override
|
||||
protected void run(CommandContext ctx, CrossLinkRegisterCts cts, CrossLinkRegisterStc.Builder stcBuilder) {
|
||||
String expected = acceptProperties.getExpectedToken();
|
||||
// 跨服未配置 expected-token 时不校验,方便本地多区服联调;生产环境建议两边配置一致
|
||||
if (StringUtils.hasText(expected) && !expected.equals(cts.getToken())) {
|
||||
stcBuilder.setOk(false).setMessage("token mismatch");
|
||||
return;
|
||||
}
|
||||
// server_id 用于日志、路由扩展;空则拒绝,避免匿名连接占坑
|
||||
if (!StringUtils.hasText(cts.getServerId())) {
|
||||
stcBuilder.setOk(false).setMessage("server_id required");
|
||||
return;
|
||||
}
|
||||
stcBuilder.setOk(true).setMessage("ok " + cts.getServerId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.huangzj.cross.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* 跨服侧:区服注册时可选的 token 校验(为空则不校验)。
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ConfigurationProperties(prefix = "cross.link")
|
||||
public class CrossLinkAcceptProperties {
|
||||
|
||||
/** 非空时须与区服 {@code cross.token} 一致才允许注册。 */
|
||||
private String expectedToken = "";
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.huangzj.cross.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* 跨服进程自己监听的 TCP 端口,长度前缀 + Protobuf 那一套。
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
@ConfigurationProperties(prefix = "cross.tcp")
|
||||
public class CrossTcpProperties {
|
||||
|
||||
/** Netty 监听端口,长度前缀 + protobuf 帧。 */
|
||||
private int port;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.huangzj.cross.net;
|
||||
|
||||
import com.huangzj.base.cmd.CommandSource;
|
||||
import com.huangzj.base.cmd.ProtoRegistry;
|
||||
import com.huangzj.base.frame.LengthPrefixedProtobuf;
|
||||
import com.huangzj.base.net.CmdRpcTcpFrameHandler;
|
||||
import com.huangzj.cross.cmd.CrossGameCommandRegistry;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/** 跨服 TCP:pipeline 上挂帧解码 + CmdRpc 业务 handler。 */
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class CrossTcpChannelInitializer extends ChannelInitializer<SocketChannel> {
|
||||
|
||||
private final CrossGameCommandRegistry crossGameCommandRegistry;
|
||||
private final ProtoRegistry protoRegistry;
|
||||
|
||||
@Override
|
||||
protected void initChannel(SocketChannel ch) {
|
||||
ch.pipeline().addLast(LengthPrefixedProtobuf.newTcpFrameDecoder());
|
||||
ch.pipeline()
|
||||
.addLast(
|
||||
new CmdRpcTcpFrameHandler(
|
||||
crossGameCommandRegistry, null, CommandSource.CROSS_TCP, protoRegistry));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package com.huangzj.cross.net;
|
||||
|
||||
import com.huangzj.cross.config.CrossTcpProperties;
|
||||
import io.netty.bootstrap.ServerBootstrap;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import java.net.BindException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* 跨服侧的 TCP 入口:Spring 起来之后绑端口,应用关掉时把线程组也收干净。
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class CrossTcpServer {
|
||||
|
||||
private final CrossTcpProperties properties;
|
||||
private final CrossTcpChannelInitializer crossTcpChannelInitializer;
|
||||
private EventLoopGroup bossGroup;
|
||||
private EventLoopGroup workerGroup;
|
||||
private Channel serverChannel;
|
||||
|
||||
/** 等 Spring 容器就绪再绑端口,避免 Bean 还没齐就开始接连接。 */
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
public void start() throws InterruptedException {
|
||||
bossGroup = new NioEventLoopGroup(1);
|
||||
workerGroup = new NioEventLoopGroup();
|
||||
try {
|
||||
ServerBootstrap b = new ServerBootstrap();
|
||||
b.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.childHandler(crossTcpChannelInitializer);
|
||||
serverChannel = b.bind(properties.getPort()).sync().channel();
|
||||
log.info("Cross TCP {}", properties.getPort());
|
||||
} catch (Exception e) {
|
||||
if (findBindException(e) != null) {
|
||||
shutdownGroupsOnly();
|
||||
int port = properties.getPort();
|
||||
throw new IllegalStateException(
|
||||
"跨服 TCP 端口 "
|
||||
+ port
|
||||
+ " 已被占用(Address already in use)。请关闭占用该端口的进程,或在 application.yml 里修改 cross.tcp.port。"
|
||||
+ " Windows 可查:netstat -ano | findstr :" + port,
|
||||
e);
|
||||
}
|
||||
shutdownGroupsOnly();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private static BindException findBindException(Throwable t) {
|
||||
while (t != null) {
|
||||
if (t instanceof BindException) {
|
||||
return (BindException) t;
|
||||
}
|
||||
t = t.getCause();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** 绑定失败时尚未 assign serverChannel,只收掉线程组,避免泄漏。 */
|
||||
private void shutdownGroupsOnly() {
|
||||
if (bossGroup != null) {
|
||||
bossGroup.shutdownGracefully(0, 1, TimeUnit.SECONDS).syncUninterruptibly();
|
||||
bossGroup = null;
|
||||
}
|
||||
if (workerGroup != null) {
|
||||
workerGroup.shutdownGracefully(0, 1, TimeUnit.SECONDS).syncUninterruptibly();
|
||||
workerGroup = null;
|
||||
}
|
||||
}
|
||||
|
||||
/** 进程退出时把 channel 和线程组都关掉,别留一堆 Netty 线程 hanging。 */
|
||||
@PreDestroy
|
||||
public void stop() throws InterruptedException {
|
||||
if (serverChannel != null) {
|
||||
serverChannel.close().syncUninterruptibly();
|
||||
}
|
||||
if (bossGroup != null) {
|
||||
bossGroup.shutdownGracefully(0, 1, TimeUnit.SECONDS).syncUninterruptibly();
|
||||
}
|
||||
if (workerGroup != null) {
|
||||
workerGroup.shutdownGracefully(0, 1, TimeUnit.SECONDS).syncUninterruptibly();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
# 开发环境
|
||||
cross:
|
||||
tcp:
|
||||
port: 9200
|
||||
link:
|
||||
expected-token: ""
|
||||
|
||||
app:
|
||||
logging:
|
||||
dir: logs/CrossModule
|
||||
@@ -0,0 +1,10 @@
|
||||
# 部署环境:监听端口、注册校验 token、日志目录建议走环境变量
|
||||
cross:
|
||||
tcp:
|
||||
port: ${CROSS_TCP_PORT:9200}
|
||||
link:
|
||||
expected-token: ${CROSS_LINK_EXPECTED_TOKEN:}
|
||||
|
||||
app:
|
||||
logging:
|
||||
dir: ${APP_LOG_DIR:/var/log/comm-framework/cross}
|
||||
@@ -0,0 +1,5 @@
|
||||
spring:
|
||||
application:
|
||||
name: cross-module
|
||||
profiles:
|
||||
active: ${SPRING_PROFILES_ACTIVE:dev}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<!-- 目录由本模块 application.yml 的 app.logging.dir 指定,与 ServerModule 互不干扰 -->
|
||||
<springProperty name="LOG_DIR" scope="context" source="app.logging.dir" defaultValue="logs/CrossModule"/>
|
||||
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
|
||||
|
||||
<!-- INFO、WARN:不含 ERROR,便于日常浏览 -->
|
||||
<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_DIR}/info.log</file>
|
||||
<encoder>
|
||||
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>DENY</onMatch>
|
||||
<onMismatch>NEUTRAL</onMismatch>
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_DIR}/info.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
<maxHistory>14</maxHistory>
|
||||
<totalSizeCap>512MB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!-- ERROR 单独落盘,告警/排障只盯这个文件即可 -->
|
||||
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_DIR}/error.log</file>
|
||||
<encoder>
|
||||
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_DIR}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
<maxHistory>30</maxHistory>
|
||||
<totalSizeCap>512MB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!-- DEBUG 仅进控制台(若把 root 调到 DEBUG);需要落盘时在 application.yml 里单独配 logger + appender -->
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<appender-ref ref="FILE_INFO"/>
|
||||
<appender-ref ref="FILE_ERROR"/>
|
||||
</root>
|
||||
</configuration>
|
||||
@@ -0,0 +1,10 @@
|
||||
# 开发环境
|
||||
cross:
|
||||
tcp:
|
||||
port: 9200
|
||||
link:
|
||||
expected-token: ""
|
||||
|
||||
app:
|
||||
logging:
|
||||
dir: logs/CrossModule
|
||||
@@ -0,0 +1,10 @@
|
||||
# 部署环境:监听端口、注册校验 token、日志目录建议走环境变量
|
||||
cross:
|
||||
tcp:
|
||||
port: ${CROSS_TCP_PORT:9200}
|
||||
link:
|
||||
expected-token: ${CROSS_LINK_EXPECTED_TOKEN:}
|
||||
|
||||
app:
|
||||
logging:
|
||||
dir: ${APP_LOG_DIR:/var/log/comm-framework/cross}
|
||||
@@ -0,0 +1,5 @@
|
||||
spring:
|
||||
application:
|
||||
name: cross-module
|
||||
profiles:
|
||||
active: ${SPRING_PROFILES_ACTIVE:dev}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<!-- 目录由本模块 application.yml 的 app.logging.dir 指定,与 ServerModule 互不干扰 -->
|
||||
<springProperty name="LOG_DIR" scope="context" source="app.logging.dir" defaultValue="logs/CrossModule"/>
|
||||
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||
<include resource="org/springframework/boot/logging/logback/console-appender.xml"/>
|
||||
|
||||
<!-- INFO、WARN:不含 ERROR,便于日常浏览 -->
|
||||
<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_DIR}/info.log</file>
|
||||
<encoder>
|
||||
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>INFO</level>
|
||||
</filter>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>DENY</onMatch>
|
||||
<onMismatch>NEUTRAL</onMismatch>
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_DIR}/info.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
<maxHistory>14</maxHistory>
|
||||
<totalSizeCap>512MB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!-- ERROR 单独落盘,告警/排障只盯这个文件即可 -->
|
||||
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<file>${LOG_DIR}/error.log</file>
|
||||
<encoder>
|
||||
<pattern>${FILE_LOG_PATTERN}</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<fileNamePattern>${LOG_DIR}/error.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
|
||||
<maxFileSize>10MB</maxFileSize>
|
||||
<maxHistory>30</maxHistory>
|
||||
<totalSizeCap>512MB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
</appender>
|
||||
|
||||
<!-- DEBUG 仅进控制台(若把 root 调到 DEBUG);需要落盘时在 application.yml 里单独配 logger + appender -->
|
||||
<root level="INFO">
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
<appender-ref ref="FILE_INFO"/>
|
||||
<appender-ref ref="FILE_ERROR"/>
|
||||
</root>
|
||||
</configuration>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
com\huangzj\cross\config\CrossTcpProperties.class
|
||||
com\huangzj\cross\net\CrossTcpServer$1.class
|
||||
com\huangzj\cross\cmd\CrossGameCommandRegistry.class
|
||||
com\huangzj\cross\CrossModuleApplication.class
|
||||
com\huangzj\cross\net\CrossTcpCommandHandler.class
|
||||
com\huangzj\cross\net\CrossTcpServer.class
|
||||
com\huangzj\cross\cmd\CrossForwardCommand.class
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
F:\coding\comm-framework\CrossModule\src\main\java\com\huangzj\cross\cmd\CrossGameCommandRegistry.java
|
||||
F:\coding\comm-framework\CrossModule\src\main\java\com\huangzj\cross\config\CrossTcpProperties.java
|
||||
F:\coding\comm-framework\CrossModule\src\main\java\com\huangzj\cross\CrossModuleApplication.java
|
||||
F:\coding\comm-framework\CrossModule\src\main\java\com\huangzj\cross\net\CrossTcpServer.java
|
||||
F:\coding\comm-framework\CrossModule\src\main\java\com\huangzj\cross\cmd\CrossForwardCommand.java
|
||||
F:\coding\comm-framework\CrossModule\src\main\java\com\huangzj\cross\net\CrossTcpCommandHandler.java
|
||||
Reference in New Issue
Block a user