外观
antispam-file — 文档 / 压缩包内容反垃圾检测(文件解析 → 元素送检 → 结果回调)
分层:解决方案层(Facade + 异步 Worker) | 部署单元:5 个(有 Dockerfile) | 数据库:TiDB(库
antispam) | base image:private-registry.nis.netease.com/library/base-image:jdk8
一、模块定位与架构
业务定位:antispam-file 负责文档类内容的反垃圾检测,覆盖 Office / PDF / 纯文本 / 压缩包等文件的解析、元素拆分、送下游文本与图片引擎检测,以及检测结果的入库与回调。它本身不做识别算法,而是做「文件 → 可检测元素 → 引擎结果 → 客户回调」的编排与状态机。
架构分层:
| 层 | 子模块目录 | 职责 |
|---|---|---|
| 协议层 | facade/http-api、facade/dubbo-provider、checker | 对外 HTTP 查询/回调/反馈、内部 Dubbo 服务、Kafka 检测入口 |
| 逻辑层 | service/business、service/base、parser、common、domain | ES/Kafka/Redis 封装、MyBatis DAO 与 Manager、文件解析库、枚举常量、实体与 DTO |
| 数据层 | MySQL/TiDB、Elasticsearch、Redis Sentinel、Kafka | 任务与结果持久化、检索、缓存/锁、异步消息 |
关键数据流:
- 客户端 →
http-api:提交文件检测任务(含内容上传),任务落库并投递 Kafka。 checker消费Antispam_FileSolution_Check_N:下载文件 → 解析 → 拆分文本/图片元素。checker将元素送下游文本/图片检测能力(http://as.test.dun.163.com/v1/file/parse/submit等)。storage消费结果消息:写 DB/ES,并按需触发主动回调。http-api:对外提供查询、被动回调、反馈审核;scheduler兜底重试回调与超时/积压处理。scheduler(ElasticJob)扫描解析/送检/回调各阶段,做补偿与重试。
二、可部署服务清单
| 部署单元目录 | artifactId | 镜像名 | 端口 | 服务类型 | 独立 Dockerfile | 是否进 kubernetes.yml |
|---|---|---|---|---|---|---|
checker | antispam-file-solution-checker | antispam-file-solution-checker | 无(非 Web) | Kafka Worker(解析 + 送检) | 有 | 是(replicas=2) |
facade/dubbo-provider | antispam-file-solution-facade-dubbo-provider | antispam-file-solution-facade-dubbo-provider | Dubbo 协议端口(未显式配置,走默认) | Dubbo Provider | 有 | 是(replicas=2) |
facade/http-api | antispam-file-solution-facade-http | antispam-file-solution-facade-http-api | 18809(private 覆写为 8080) | HTTP(查询 / 回调 / 反馈) | 有 | 是(replicas=2) |
storage | antispam-file-solution-storage | antispam-file-solution-storage | 无 | Kafka Consumer(结果入库 + 回调) | 有 | 是(replicas=2) |
scheduler | antispam-file-solution-scheduler | antispam-file-solution-scheduler | 无 | ElasticJob 定时任务 | 有 | 否 |
console/api | antispam-file-solution-console-api | — | 8080 | 控制台 HTTP | 无(不构建) | 否 |
- 镜像推送仓库为
private-registry.nis.netease.com/yidun,而kubernetes.yml拉取的是private-registry.yidun.internal/yidun/*:1.0.0.private,仓库主机不一致(见第七节)。 scheduler有Dockerfile但无build.sh,因此不会被根目录buildAll.sh的find . -name build.sh循环命中,也不会进入kubernetes.yml。
三、同模块启动顺序
storage—— 先让结果落库/建索引的通路就绪,避免后续消费到的检测结果无处可写。checker—— 文件解析与送检 Worker 上线,但此时生产者不活跃,可安全冷启动。http-api—— 打开客户提交通路;此时 storage 已可消费,链路完整。dubbo-provider—— 注册内部 Dubbo 服务,供其它模块查询复用。scheduler—— 最后开闸:一旦启动即按 cron 向Antispam_FileSolution_Check_N投递/推动任务,过早启动会在下游未就绪时制造积压。
四、逐服务启动逻辑
checker
- 启动类:
com.netease.is.antispam.file.solution.checker.CheckerApplication(checker/src/main/java/com/netease/is/antispam/file/solution/checker/CheckerApplication.java)。 @SpringBootApplication:无 exclude。@Enable*:@EnableCdcDataSubscribe、@EnableOssClient、@EnableBusinessClient、@EnableRecoverComponent、@EnableConfigurationProperties({FileSolutionProperties.class})。- 组件扫描:与启动类同包的
checker.configuration.CheckerConfiguration(@ComponentScan:file.solution.service/manager/component/component.recover+@MapperScan("com.netease.is.antispam.file.solution.dao"));checker.configuration.KafkaConfiguration(@EnableKafka)。 - Kafka 关键参数(
KafkaConfiguration):enable.auto.commit=false、max.partition.fetch.bytes=20971520、max.poll.records=100,kafkaListenerContainerFactory的concurrency=1(固定单并发)。 main()自定义逻辑:System.setProperty("javax.xml.parsers.DocumentBuilderFactory", "com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl")(JAXP 实现强制指定,不可删,否则文档解析可能出现工厂解析异常)。- 启动钩子:
com.netease.is.antispam.file.solution.checker.configuration.YidunQosApplication(@QosRegister)。doOffline()停止KafkaListenerEndpointRegistry与全部ConcurrentMessageListenerContainer后Thread.sleep(3000L),用于优雅下线。
facade/dubbo-provider
- 启动类:
com.netease.is.antispam.file.solution.facade.dubbo.DubboApplication。 @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})。@Enable*:@EnableAspectJAutoProxy、@EnableCdcDataSubscribe、@EnableOssClient、@EnableConfigurationProperties({FileSolutionProperties.class})、@EnableRecoverComponent。无@EnableApolloConfig(properties 里存在app.id=antispam-file与apollo.bootstrap.*,但缺注解入口)。- 组件扫描:
facade.dubbo.configuration.DubboFacadeConfiguration(@ComponentScan:service、manager、component.limiter/op/cdc/recover+@MapperScan(...dao))。 - 数据源:
facade.dubbo.configuration.DynamicDataSourceConfiguration—— DruidmasterDataSource(spring.datasource.master)、mirrorDataSource(spring.datasource.mirror),并暴露@Primary的DynamicDataSource(Master/Mirror物理源映射)。 main()无自定义逻辑;启动钩子:未发现。
facade/http-api
- 启动类:
com.netease.is.antispam.file.solution.facade.http.HttpApplication。 @SpringBootApplication(无 exclude)。@Enable*:@EnableCdcDataSubscribe、@EnableOssClient、@EnableBusinessClient、@EnableConfigurationProperties({FileSolutionProperties.class})、@EnableRecoverComponent、@ServletComponentScan、@EnableI18nComponent、@EnableApolloConfig、@EnableAspectJAutoProxy。- 组件扫描:
facade.http.configuration.HttpFacadeConfiguration implements WebMvcConfigurer(@ComponentScan含component.callback与com.netease.is.antispam.components.callback+@MapperScan(...dao))。@Bean validator()使用 HibernateValidator,hibernate.validator.fail_fast=false;addInterceptors注册GlobalControllerInterceptor拦截/**。 - 配置:
server.port=18809(application-private.properties覆写为 8080),app.id=antispam-file-http,Apollo 命名空间application,file-http,端口dubbo.registry.group=/yidun/antispam/online-new/yidun-antispam-dubbo。 main()无自定义;启动钩子:未发现。
storage
- 启动类:
com.netease.is.antispam.file.solution.storage.StorageApplication。 @SpringBootApplication+@EnableOssClient、@EnableBusinessClient、@EnableRecoverComponent、@EnableCdcDataSubscribe、@EnableApolloConfig、@EnableConfigurationProperties({FileSolutionProperties.class})。- 组件扫描:
storage.configuration.StorageConfiguration(@ComponentScan含component.check.submitter、components.callback+@MapperScan(...dao));storage.configuration.KafkaConfiguration(@EnableKafka,kafkaListenerContainerFactory的concurrency=8)。 - Kafka 双通道:Spring Kafka(
spring.kafka,group-id=file-solution-storage、max.poll.records=100)+ 易盾组件消费netease.kafka.consumer.cluster.new(max.poll.records=20、max.poll.interval.ms=600000)。 - 业务参数:
file.dealpool.consumer.maxwait.count=10;app.id=antispam-file-storage,Apollo 命名空间application,file-storage,antispam-privatization-common。 - 启动钩子:
storage.YidunQosApplication(停 Kafka 容器 + sleep,与 checker 同实现)。
scheduler
- 启动类:
com.netease.is.antispam.file.solution.scheduler.SchedulerApplication。 @SpringBootApplication+@EnableElasticJob、@EnableScheduling、@EnableOssClient、@EnableConfigurationProperties({FileSolutionProperties.class})、@EnableBusinessClient、@EnableRecoverComponent、@EnableApolloConfig、@EnableCdcDataSubscribe、@EnableDubbo。- 组件扫描:
scheduler.configuration.SchedulerTaskConfiguration(任务包 + integration + kafka +components.callback)。 - ElasticJob 作业(
application.properties):fileParseTaskDealWorker(0/3s,分片 15)、fileItemSendCheckWorker(0/3s,分片 10)、fileParseTaskDealRecoverWorker(0/20s)、fileDataLockRecordReleaseWorker(*/5s)、fileDataCheckFinishWorker、compressFileCheckFinishWorker、fileActiveCallbackRetryWorker、fileAutoCallbackRetryWorker、fileCheckOverStockNoticeWorker、fileParseCallbackTaskDealWorker、fileCreateWorkerTaskDealWorker;fileCheckTimeoutWorker2.enable=false(已停用)。 - 配置:
app.id=antispam-file_scheduler,Apollo 命名空间application,file_scheduler;ElasticJob ZK private 见各 profile。 - 启动钩子:
scheduler.YidunQosApplication。
五、启动前置依赖
| 依赖 | 配置键 / 地址 | 阻塞 or 弱依赖 | 配置文件 |
|---|---|---|---|
| Apollo | 无显式 meta(各 profile 内置);app.id / apollo.bootstrap.namespaces | 弱(未下发时用本地默认) | application*.properties |
| TiDB | spring.datasource.*;tidb-cluster0-tidb.tidb.svc:4000/antispam | 阻塞 | application-private.properties |
| Redis Sentinel | spring.redis.sentinel.master=master01、...nodes=redis0-redis-ha.yidun-infra.svc:26379 | 阻塞 | application-private.properties |
| ZooKeeper(Dubbo 注册) | dubbo.registry.address=zookeeper://zk-0/1/2.zookeeper.yidun-infra:2181;dubbo.registry.group=/yidun/antispam/online-new/yidun-antispam-dubbo | 阻塞 | application-private.properties |
| ZooKeeper(business client) | business.client.options.zookeeper.rootPath=/netease-antispam/online/config | 阻塞 | application-private.properties |
| Kafka | spring.kafka.bootstrap-servers=kafka-yidun-0/1/2...:9092、cdc.kafka.bootstrap-servers | 阻塞 | application-private.properties |
| ElasticJob ZK | elastic.job.zk.server-lists(scheduler 专属) | 阻塞(仅 scheduler) | scheduler/application-{test,online,...}.properties |
| OSS | nos.netease.com、nos-jd.service.163.org | 弱 | application.properties |
| 下游检测 HTTP | http://as.test.dun.163.com/v1/file/parse/submit 等 | 弱(失败可重试) | application-private.properties |
六、启动参数与 Profile
- Spring profiles:默认
spring.profiles.active=dev;容器统一-Dspring.profiles.active=private(Dockerfile ENV JAVA_OPTS)。 - Maven profile(根
pom.xml):default(activeByDefault)、test、online、private、jiande-online、private-bes(宝兰德 BES 内嵌容器)。作用为设置deploy.env驱动资源过滤<filter>src/main/filter/${deploy.env}.properties</filter>。 - JAVA_OPTS:
checker=-Xmx1024m -Xms1024m -XX:+UseG1GC -Dspring.profiles.active=private;其余单元-Xmx512m -Xms512m+ 同款 GC/Profile。 - base image 与仓库:
FROM private-registry.nis.netease.com/library/base-image:jdk8;推送仓库private-registry.nis.netease.com/yidun;tag1.0.0.private。 checker额外RUN apk add --no-cache unrar(需解析 RAR 压缩包)。- 构建:
buildAll.sh→mvn clean install -Pprivate→ 遍历build.sh(-c false -p false -e private)→docker buildx build --platform linux/amd64,linux/arm64 --push→ 调podupdate.sh更新 Pod。
七、启动期踩坑
storage/build.sh的MODEL_NAME=checker:storage目录的构建脚本里MODEL_NAME误设为checker(复制粘贴遗留),会编译错模块。- Dockerfile
COPY与finalName不匹配:除checker(<finalName>antispam-file-solution-checker</finalName>)外,其余单元finalName均为${project.artifactId}-${project.version}-application,而 Dockerfile 写死COPY ./target/${APP_NAME}.jar(APP_NAME为不带版本后缀的镜像名)→docker build阶段 COPY 找不到文件而失败。 scheduler不在kubernetes.yml,且无build.sh:定时补偿任务不会随清单部署,也不被buildAll.sh构建,需人工处理。CheckerApplication.main的 DocumentBuilderFactory 设置不可删:删除后文档解析相关 XML 工厂可能抛异常。checker无 Apollo 注解入口 / 无@EnableApolloConfig:改配置只能重打镜像或改 profile 文件,无法走配置中心热更。dubbo-provider无@EnableApolloConfig:虽然application.properties里有app.id与apollo.bootstrap.*,但缺注解入口,Apollo 生效性存疑。checkerKafka 消费者并发固定为 1:kafkaListenerContainerFactory.setConcurrency(1),分区横向扩展能力受限,需靠多副本分摊。- 仓库主机不一致:
build.sh推送private-registry.nis.netease.com/yidun,kubernetes.yml拉取private-registry.yidun.internal/yidun*;镜像 tag 也要人工对齐1.0.0.private。 kubernetes.yml探针缩进错误:readinessProbe被错误地嵌套在livenessProbe的字段之下,readinessProbe实际不会生效。
八、跨模块前置
- 下游文本 / 图片检测能力(文本、图片业务服务的 Dubbo/HTTP)必须先可用,否则
checker送检全量失败并堆积。 - 公共组件配置中心:Apollo
application命名空间 +antispam-privatization-common的公共配置需先就绪。 - 共享基础设施:Kafka(
kafka-yidun-*)、ZooKeeper(zk-0/1/2.zookeeper.yidun-infra:2181)、Redis Sentinel(redis0-redis-ha.yidun-infra.svc:26379)、TiDB(tidb-cluster0-tidb.tidb.svc:4000)由平台侧统一提供,需先于本模块启动。 - OSS 对象存储:文件原件与解析产物依赖 OSS,桶
yidun-antispam-solution需已创建并授权。