外观
antispam-rule — 规则检测中台(规则全生命周期管理 + 在线分片命中判定)
分层:反垃圾产品业务层(规则检测与治理中台)| 部署单元:6 个有 Dockerfile(k8s 部署其中 4 个)| 数据库:MySQL/TiDB
antispam(check-provider 无 DB)| base image:private-registry.nis.netease.com/library/base-image:jdk17(tagbase-250409)
一、模块定位与架构
它把“垃圾内容靠什么规则识别、识别后怎么处置”两件事做成中台:管理侧让运营/审核配置可复用、可上线、可下线的规则(条件、匹配器、过滤器、高频统计、词库、样本集);检测侧在请求到来时实时执行规则,输出命中结果与建议动作(通过/先发后审/先审后发/删除/加黑)。
架构分层
- 协议层(检测):
facade/dubbo-check-api的RuleCheckFacade→facade/dubbo-check-provider的RuleCheckProvider(扇出到 checker 分片) - 引擎层:
service/business/checker/chain(CheckExecChainHolder责任链:动作调整 → 预处理 → 超时 → 长文本分段 → 主检测) - 执行层:
service/base/checker(RuleExecutor)+common(匹配器/过滤器/正则/词库) - 检测运行体:
checker(每 target 一个TargetRuleChecker+RuleCheckerSet,RuleSetManager默认 2 分钟刷新规则) - 管理侧:
service/business+facade/dubbo-provider(RuleFacade)+facade/http-api(ShenYu 网关) +scheduler(自动上线/下线/性能评估/同步) - 数据加载:
datacenter/antispam-rule_data-loader(RuleSetDataLoadManager/RuleRemoteService把规则集、正则索引树、股票词库加载进检测侧内存)
关键数据流
RuleCheckFacade.checkV2→RuleCheckProviderRestTemplateRemote.call按分片 →checker的CheckController.rule/check/{shard}/{replica}CheckExecChainHolder.doExecute→MainCheckWithIndexExec(串/并行策略)RuleExecutor.executeRule→RuleCheckUtils.isMeet条件匹配- 命中结果与建议动作回传调用方
二、可部署服务清单
| 部署单元目录 | artifactId | 镜像名 | 端口 | 服务类型 | 独立 Dockerfile | 是否进 kubernetes.yml |
|---|---|---|---|---|---|---|
checker | antispam-rule-checker | private-registry.yidun.internal/yidun/antispam-rule-checker:1.0.0.private | 18020(base) / 18031(private),Undertow worker-threads=600 | HTTP(检测分片) | 有 | 是(replicas=4) |
facade/dubbo-provider | antispam-rule-facade-dubbo-provider | private-registry.yidun.internal/yidun/antispam-rule-dubbo-provider:1.0.0.private | Dubbo port=-1 | Dubbo Provider(规则管理) | 有 | 是(replicas=2) |
facade/dubbo-check-provider | antispam-rule-facade-dubbo-check-provider | private-registry.yidun.internal/yidun/antispam-rule-dubbo-check-provider:1.0.0.private | Dubbo port=-1 | Dubbo Provider(检测入口) | 有 | 是(replicas=2) |
scheduler | antispam-rule-scheduler | private-registry.yidun.internal/yidun/antispam-rule-scheduler:1.0.0.private | 无 Web | ElasticJob + Kafka Consumer | 有 | 是(replicas=1) |
facade/http-api | antispam-rule-facade-http(finalName=antispam-rule-facade-http-api) | 若构建为 antispam-rule-facade-http-api:base-250409 | 18018(base) | HTTP(ShenYu 网关接入) | 有 | 否 |
datacenter/antispam-rule_data-loader | antispam-rule_data-loader | 若构建为 antispam-rule-data-loader:base-250409 | 18020(base) | 规则数据加载器 | 有 | 否 |
console/api | antispam-rule-console-api | 无(不构建) | — | 控制台后端 | 无 | 否 |
benchmark | antispam-rule-benchmark | 无(不构建,JMH 基准) | — | 性能基准 | 无 | 否 |
三、同模块启动顺序
datacenter/antispam-rule_data-loader—— 先起,负责把规则集/正则索引/词库准备好(有 Dockerfile 但不在 k8s,需按需部署)。facade/dubbo-provider—— 规则管理与 Dubbo 契约注册主体,提供RuleFacade,是数据与策略的来源。checker(Sharding Provider) —— 向 ZK 发布规则分片(rule.sharding.registry.zookeeper.*,group=online,zone.count=2),必须先于 Customer 侧。facade/dubbo-check-provider(Sharding Customer) —— 从 ZK 订阅 checker 发布的分片数据,依赖 checker 先就绪。scheduler—— 定时任务消费 Kafka、自动上下线、性能评估;依赖 DB 与规则数据已存在。facade/http-api—— 对外 HTTP(ShenYu)接入,最后启动。
四、逐服务启动逻辑
checker
- 启动类:
com.netease.is.antispam.rule.checker.CheckerApplication(checker/src/main/java/.../CheckerApplication.java) @SpringBootApplication:无 exclude;@EnableRuleCheckerChain、@EnableShardingProvider、@EnableBusinessClient、@EnableApolloConfig、@EnableConfigurationProperties({RuleCheckerProperties, RegistryProperties, ProviderProperties, RuleFilterProperties})@EnableShardingProvider→@Import(ProviderConfiguration)(service/business/.../sharding/provider/):注册ProviderAutoRegistry、ProviderMetadataHolder、ProviderApplicationListener(向 ZK 发布规则分片)HttpFacadeConfiguration(checker/.../configuration/):@ComponentScan({...rule.service, ...rule.manager, ...rule.component, ...rule.checker, ...rule.filter})+@MapperScan("...rule.dao");注册PopoClient、CircuitBreakerConfigRegistry、WebQosHealthInterceptor、CustomHealthWebMvcConfigurermain():run后ServiceStatus.setStatus(ServiceStatus.STARTED)- 启动钩子(大量
@PostConstruct预热):RuleSetManager、RuleSetLoadCache、RuleSetDataLoadManager、RuleGeneralConfigLoadCache、RuleSampleSetCache、RegexHelperCache、CheckExecChainHolder、RuleTargetConfigCache、TargetRuleCheckerCache、RuleCheckStrategySelector、StrategyRuleFilter等,另有ContextRefreshedEventListener
facade/dubbo-check-provider
- 启动类:
com.netease.is.antispam.rule.facade.dubbo.CheckDubboApplication @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class})—— 无 DB@EnableAspectJAutoProxy、@EnableBusinessClient、@EnableApolloConfig、@EnableShardingCustomer、@EnableConfigurationProperties({RuleDubboCheckDynamicProperties.class})@EnableShardingCustomer→@Import(CustomerConfiguration)(service/business/.../sharding/customer/):注册CustomerAutoSubscription、CustomerApplicationListener、CustomerMetadataHolder、PoolingHttpClientConnectionManager的HttpClient、线程池remote-call-%d的RestTemplateRemoteApplicationConfiguration(facade/dubbo-check-provider/.../configuration/):仅@ComponentScan({...rule.checker.pretreatment, ...rule.hint.util})- 关键配置:
dubbo.application.id=antispam-rule-check-dubbo、dubbo.protocol.dispatcher=message、dubbo.protocol.threads=400、dubbo.protocol.payload=83886080(80MB)、dubbo.protocol.threadpool=simplefixed、dubbo.provider.warmup=200000、netease.kafka.producer.enable=false、rule.sharding.customer.http.pool-size/max-total=2000 main():仅 run;启动钩子:未发现显式@PostConstruct(Sharding Customer 通过 Spring 事件订阅)
facade/dubbo-provider
- 启动类:
com.netease.is.antispam.rule.facade.dubbo.DubboApplication @EnableDistributeId、@EnableBusinessClient、@EnableApolloConfig、@SpringBootApplication、@EnableAspectJAutoProxy、@EnableTransactionManagement、@EnableConfigurationProperties({RuleBusinessProperties, RuleCheckerRemoteProperties, RuleCheckerProperties, RuleFilterProperties})ApplicationConfiguration:@ComponentScan({...rule.cache, ...rule.service, ...rule.manager, ...rule.component, ...rule.filter, ...rule.checker.pretreatment})+@MapperScan("...rule.dao");注册FrequencyMonitorRedisTemplate(IFrequencyMonitor)、SimilarCheckService、RuleExecutor、PinyinTableFilterRefreshWorker- 关键配置:
app.id=antispam-rule_dubbo、dubbo.protocol.payload(80MB 级)、elasticsearch.multiple.config.servers=http://yidun-db-middleware-dev-1.jd.163.org:7000,...、distribute.id.namespace=antispam-rule-sample - 启动钩子:
RuleConditionMetadataStrategyDataSyncProvider、RuleFilterConfigStrategyDataSyncProvider、RuleStrategyDataSyncProvider的@PostConstruct(把策略元数据/过滤配置/策略数据同步到 ZK);main()仅 run
facade/http-api
- 启动类:
com.netease.is.antispam.rule.facade.http.HttpApplication @SpringBootApplication、@EnableConfigurationProperties({RulePrivatisationProperties, RuleFilterProperties})、@EnableRateLimiter、@EnableBusinessClient、@EnableApolloConfig、@Controller、@ShenyuSpringMvcClient(path="/rule-shenyu/**")(注册到 ShenYu 网关)- 关键配置:
server.port=18018、app.id=rule-http、shenyu.register.enabled=false(base 关闭注册)、spring.cloud.sentinel.enabled=false、business.client.options.operateTargetTypes=TARGET,PRODUCT - 启动钩子:
RuleHttpApolloConfig.@PostConstruct、RuleSetDataCache/RuleSetMemoryCache的@PostConstruct;main()仅 run
datacenter/antispam-rule_data-loader
- 启动类:
com.netease.is.antispam.rule.datacenter.loader.RuleLoaderApplication @SpringBootApplication、@EnableApolloConfig、@EnableAspectJAutoProxy、@EnableTransactionManagement、@EnableConfigurationProperties({RuleCheckerProperties.class, RuleLoaderProperties.class})- 关键配置:
server.port=18020(与 checker base 同端口)、app.id=rule_data-loader、dubbo.protocol.payload=209715200(200MB)、rule.load.rule-set-index-threshold=2、rule.load.enable-regex-helper=false - 启动钩子:
RuleDataLoadQpsUtil.@PostConstruct;main()仅 run
scheduler
- 启动类:
com.netease.is.antispam.rule.scheduler.SchedulerApplication @SpringBootApplication、@EnableAspectJAutoProxy、@EnableElasticJob、@EnableBusinessClient、@EnableTransactionManagement、@EnableConfigurationProperties({RuleCheckerRemoteProperties, RuleCheckerProperties, RuleFilterProperties})、@EnableScheduling、@EnableApolloConfigKafkaConfiguration(scheduler 模块内):@EnableKafka+ 手写DefaultKafkaConsumerFactory(bootstrap.servers=${app.kafka.bootstrap.servers}、group.id=${app.kafka.consume.group.id}、enable.auto.commit=false、max.partition.fetch.bytes=10485760、max.poll.records=100)+KafkaTemplate- ElasticJob:13 个
@ElasticJobConf(ruleAnalyzeWorker、ruleAutoOfflineWorker、ruleAutoOnlineWorker、ruleEvaluatePerformanceWorker、ruleRefreshDataSyncWorker、ruleValidateWorker(V2)、stockUpdateWorker、vocabularyValidationWorker、ruleSampleSetStatusFxiWorker等);base 全部elastic.job.<worker>.disabled=true,private 覆写部分为false;elastic.job.zk.namespace=netease-antispam-rule-jobs-online - 启动钩子:
SchedulerApolloConfig.@PostConstruct、多个 Worker 的@PostConstruct、AbstractStatConsumer implements InitializingBean;内置YidunQosApplication;main()仅 run
五、启动前置依赖
| 依赖 | 配置键 / 地址 | 阻塞 or 弱依赖 | 配置文件 |
|---|---|---|---|
| MySQL/TiDB | spring.datasource.url=jdbc:mysql://tidb-cluster0-tidb.tidb.svc:4000/antispam | 阻塞(check-provider 除外,无 DB) | application-private.properties |
| ZK — Dubbo 注册中心 | dubbo.registry.address=zookeeper://zk-0.zookeeper.yidun-infra:2181?backup=...,group /yidun/antispam/online-new/yidun-antispam-dubbo | 阻塞 | application-private.properties |
| ZK — business.client | business.client.options.zookeeper.address=zk-0/1/2.zookeeper.yidun-infra:2181,rootPath /netease-antispam/online/config | 阻塞 | application-private.properties |
| ZK — 规则分片(Sharding) | rule.sharding.registry.zookeeper.addresses=...,group=online,Provider zone.count=2,Customer pool-size=2000 | 阻塞 | application-private.properties |
| ZK — ElasticJob | elastic.job.zk.namespace=netease-antispam-rule-jobs-online | 阻塞(scheduler) | scheduler 配置 |
| ZK — 分布式 ID | distribute.id.namespace=antispam-rule-sample,distribute.id.zookeeper-host=... | 阻塞 | application.properties(dubbo-provider) |
| Redis | checker:spring.redis.sentinel.master=master01,nodes=redis0-redis-ha.yidun-infra.svc:26379,lettuce.pool.max-active=200 | 强 | application-private.properties |
| Kafka | scheduler:app.kafka.bootstrap.servers/app.kafka.consume.group.id;check-provider netease.kafka.producer.enable=false | scheduler 阻塞 / 其余弱 | application.properties |
| ES | elasticsearch.multiple.config.servers=http://yidun-db-middleware-dev-1.jd.163.org:7000,... | 弱 | application.properties |
| Apollo | app.id=rule-http / rule_dubbo-check / antispam-rule_dubbo / rule_data-loader / antispam-rule-schedule,apollo.bootstrap.enabled=true | 弱 | application.properties |
| OSS / 外部服务 | antispam.oss.default.url.prefix=...;rule.checker.remote.similar.content-check-url=http://antispam-simfreq.service.163.org/rule-simfreq;yidun.message.api.url=http://yidun-msg-api... | 弱 | application.properties(scheduler/checker) |
六、启动参数与 Profile
-Dspring.profiles.active:各单元 base 默认值不统一 ——checker/facade/dubbo-check-provider/datacenter/..._data-loader默认test;facade/dubbo-provider/facade/http-api默认dev;scheduler默认test-validate;容器统一写private- maven profile:本仓库根
pom.xml未自定义 profile,-P private由父/平台 POM 提供 - JAVA_OPTS:
checker/facade/dubbo-check-providerDockerfile 为-Xmx1024m -Xms1024m;其余 Dockerfile 为-Xmx512m -Xms512m;k8s 覆写为-Xmx1024m -Xms1024m,checker 例外覆写-Xmx2048m -Xms2048m(resources req cpu 4 / mem 2048Mi,limit cpu 8 / mem 4096Mi) - base image 与镜像仓库:
private-registry.nis.netease.com/library/base-image:jdk17;build.shDOCKER_REPOSITORY=private-registry.nis.netease.com/yidun,tagbase-250409;k8s 拉取private-registry.yidun.internal/yidun/antispam-rule-*:1.0.0.private build.sh关键参数:MODEL_NAME=checker|facade/dubbo-provider|facade/dubbo-check-provider|facade/http-api|datacenter/antispam-rule_data-loader|scheduler;BUILD_ENV=private;DOCKER_IMAGE_TAG=base-250409;docker buildx build --platform linux/amd64,linux/arm64 --push(checker/build.sh用cd ..而非cd ../..,层级与其它单元不同)
七、启动期踩坑
- dubbo-check-provider 无数据库:启动类
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, DruidDataSourceAutoConfigure.class}),spring.datasource.*完全不生效——排查“数据源未初始化”前先确认这是预期设计。 - Sentinel 默认关闭:
spring.cloud.sentinel.enabled=false(多个单元),导致spring.cloud.sentinel.datasource.degrade.file.file=classpath:sentinel/online/DegradeRule.json不生效,降级规则不会加载。 dubbo.protocol.payload极大:check-provider83886080(80MB)、data-loader209715200(200MB)—— Dubbo 单包上限被抬高,内存与网络开销随之上升。- checker 滚动更新会同时全量拉规则集:
replicas=4+RollingUpdate maxUnavailable=1 / maxSurge=4,扩缩一半以上副本同时启动,都走@PostConstruct全量加载规则/正则/词库,易造成 DB/ZK 瞬时压力。 - scheduler base 全部任务
disabled=true:13 个@ElasticJobConf在 base 全禁用,只有 private(及部分环境)覆写为启用;以 base 跑会“任务一个都不执行”,不是 BUG。 - Sharding
group=online必须 Provider/Customer 一致:checker 发布分片与 check-provider 订阅分片都依赖rule.sharding.registry.zookeeper.group=online,任一侧配错即订阅不到(检测变空)。 data-loader不在 kubernetes.yml:虽有 Dockerfile 与base-250409构建脚本,但 k8s 清单里没有对应 Deployment,需自行部署或由宿主方式提供。- base profile 各不相同:checker/dubbo-check/data-loader 为
test,dubbo-provider/http-api 为dev,scheduler 为test-validate;本地直跑不同单元会连到不同环境。
八、跨模块前置
- 配置源依赖
antispam-business:消费TargetCache/TargetConfigCache/ProductCache/TargetCheckerCache与 Target/CheckerType 实体,经 ZK/netease-antispam/online/config读取(阻塞级配置读取)。 - 关键词模型依赖
antispam-keyword:通过KeywordStrategyCheckerModelFacade/StrategyDataSyncSpi集成关键词模型;antispam-keyword未就绪时关键词类规则不可用。 - 同机协同:
antispam-list(名单检测与规则检测在同一编排中协同,pom 依赖antispam.list.dubbo)。 - 运行期弱依赖:
antispam-simfreq(相似度)、yidun-msg-api(消息通知)、ES、OSS。 - 建议启动前已在运行:
antispam-business,其次antispam-keyword、antispam-list。