4、接入层设计与实现:协议适配、连接池管理、流量整形与限流

接入层,说白了就是风控系统的「大门」。

所有交易请求,不管从哪来、用什么协议,都得先过这一关。我见过不少系统,风控逻辑写得挺漂亮,结果接入层先崩了——连接数打满、协议解析出错、流量直接把服务冲垮。嗯,这章咱们就把这扇「门」设计好。

4.1 协议适配:让不同「方言」都能对话

交易渠道五花八门。有的用HTTP,有的走TCP长连接,还有的用WebSocket做实时推送。你想想看,如果每种协议都单独写一套处理逻辑,那维护成本得多高?

我个人习惯的做法是:抽象一个统一的协议层接口,把协议差异隔离在适配器里。

核心思路: 定义统一的 Request/Response 模型,各协议适配器负责「翻译」成内部标准格式。

// 统一协议适配器接口
public interface ProtocolAdapter {
    // 将原始请求解析为内部标准请求
    StandardRequest parse(byte[] rawData);
    // 将内部标准响应编码为协议特定格式
    byte[] encode(StandardResponse response);
    // 判断是否支持该协议
    boolean supports(String protocolType);
}

我在项目中遇到过最头疼的事:某银行渠道用的HTTP,但报文格式是自定义的二进制。嗯,这时候适配器就派上用场了——你只需要写一个 BinaryHttpAdapter,其他逻辑完全不用动。

4.1.1 HTTP 适配

HTTP 是最常见的。我建议用 Servlet FilterSpring Interceptor 做统一拦截。注意一点:不要把业务逻辑写在 Filter 里,只做协议转换和基础校验。

4.1.2 TCP 适配

TCP 长连接常用于内部系统对接。这里有个坑:粘包/拆包问题。我曾经因为没处理好这个,线上数据全乱了。解决方案是用 LengthFieldBasedFrameDecoder(Netty)或者自定义分隔符。

4.1.3 WebSocket 适配

WebSocket 适合需要服务端主动推送的场景,比如交易状态实时通知。我个人习惯用 Spring WebSocket + STOMP 协议,省心不少。

4.2 连接池管理:别让连接成为瓶颈

连接池,说白了就是「复用」。每次请求都新建TCP连接?那性能肯定完蛋。

我见过最夸张的情况:某系统没配连接池,高峰期每秒新建3000个连接,直接把系统端口耗尽了。嗯,这就是典型的「连接泄漏」。

避坑指南: 我曾经因为连接池的 maxTotal 配得太大,导致数据库连接数被打满。记住:连接池不是越大越好,要根据实际并发和响应时间算。

参数 推荐值 说明
maxTotal 50-200 最大连接数,根据压测结果调整
maxIdle 10-30 最大空闲连接,避免资源浪费
minIdle 5-10 最小空闲连接,应对突发流量
maxWaitMillis 1000-3000 获取连接的超时时间,单位毫秒

我建议用 Apache Commons Pool2HikariCP。HikariCP 性能最好,但 Commons Pool2 更灵活。怎么选?看你的场景——如果只是数据库连接,HikariCP 就够了;如果还要管理 Redis、MQ 等连接,Commons Pool2 更通用。

4.3 流量整形与限流:给系统装上「安全阀」

流量整形,说白了就是「削峰填谷」。限流则是「挡在门外」。两者配合,才能让系统稳如老狗。

你想想看,双十一零点那波流量,如果不做限流,系统直接被打穿。我经历过一次,那叫一个惨——数据库连接池爆满,应用服务器CPU 100%,最后只能重启。从那以后,我再也不敢轻视限流了。

4.3.1 常用限流算法

  • 计数器算法: 最简单,但存在「临界突变」问题。比如1秒内限100次,前0.9秒没请求,后0.1秒来了100次,系统照样扛不住。
  • 滑动窗口算法: 把时间窗口切分成小格子,每个格子独立计数。比计数器平滑,但精度越高内存开销越大。
  • 漏桶算法: 请求先进入桶里,以固定速率流出。适合「平滑流量」,但无法应对突发。
  • 令牌桶算法: 以固定速率往桶里放令牌,请求来了拿令牌。允许一定程度的突发,我比较推荐这个。

我的经验: 风控系统建议用 令牌桶 + 滑动窗口 组合。令牌桶控制平均速率,滑动窗口防止突发。具体实现可以用 Guava RateLimiterSentinel

// 使用 Guava RateLimiter 实现令牌桶
RateLimiter limiter = RateLimiter.create(100.0); // 每秒100个令牌

public boolean tryAcquire() {
    // 尝试获取令牌,超时100ms
    return limiter.tryAcquire(100, TimeUnit.MILLISECONDS);
}

4.3.2 流量整形策略

流量整形不只是限流,还包括:

  • 排队等待: 请求先入队列,按优先级或时间顺序处理。我建议用 DisruptorLinkedBlockingQueue
  • 降级处理: 超过阈值后,返回「系统繁忙」或走简化流程。比如风控评分可以降级为「快速模式」。
  • 动态调整: 根据系统负载自动调整限流阈值。我做过一个方案:CPU > 80% 时,限流阈值自动降低20%。

核心原则: 限流不是目的,保证核心交易能正常处理才是。所以,限流要分优先级——VIP用户的请求,阈值可以高一些。

4.4 知识体系总览

下面这张图,把接入层的核心逻辑串起来了。你可以把它当作设计时的「检查清单」。

接入层核心架构 协议适配层 HTTP 适配器 TCP 适配器 WebSocket 适配器 连接池管理层 连接复用 连接检测 连接回收 流量整形与限流层 令牌桶算法 滑动窗口 排队降级

从图上你能看到:请求先经过协议适配层,转成统一格式;然后进入连接池管理层,复用已有连接;最后经过流量整形与限流层,决定是放行还是排队。三层各司其职,缺一不可。

一个小建议: 接入层的每个组件都要做 熔断。比如连接池满了,不要一直等,直接返回「服务暂不可用」。我习惯用 Resilience4j 做熔断,轻量又好用。

好了,接入层就聊到这儿。记住:这扇「大门」设计好了,后面的风控逻辑才能安心跑。别嫌麻烦,该做的限流、连接池、协议适配,一个都不能少。


公众号:蓝海资料掘金营,微信deep3321