外观
antispam-media-solution — 融媒体(图片/音视频/文本/文件)统一机审与人审编排方案
分层:解决方案层(Facade + Scheduler + Storage) | 部署单元:5 个(有 Dockerfile) | 数据库:TiDB | base image:private-registry.yidun.internal/yidun/base-image:jdk17
一、模块定位与架构
业务定位:antispam-media-solution 是「融媒体」统一受理层,把客户提交的图片、音视频、文本、文件等多种媒体统一登记为一个媒体任务,再分发到对应业务引擎做机审,并把机审结果编排进人审流程、账单与回调。
架构分层:
| 层 | 子模块目录 | 职责 |
|---|---|---|
| 协议层 | facade/http-check-api、facade/http-api、facade/dubbo-provider | 同步/异步提交受理、查询与主动回调、内部 Dubbo 服务 |
| 逻辑层 | service/business、service/base、common、domain、scheduler | ES/Kafka/Redis 封装、DAO 与 Manager、状态机与对账(reconciliation)、账单、定时补偿 |
| 数据层 | TiDB、Elasticsearch(归档)、Redis Sentinel、Kafka | 媒体任务与结果持久化、归档检索、缓存与分布式锁、消息总线 |
关键数据流:
- 客户端 →
http-check-api:提交媒体任务,登记并投递 Kafka(Antispam_MediaSolution_Msg/..._Top_Msg)。 scheduler:mediaDataSubmitWorker扫描待提交任务,按媒体类型分发到文本/图片/音频/视频/文件检测 HTTP 接口。- 各业务引擎 → 回写 →
storage消费Antispam_Media_Finish_Msg等:结果入库/入 ES。 scheduler的对账与回收任务(mediaSolutionunCheckWorker、dataConsistencyWorker等)补齐漏检、释放锁、清理归档。- 判定完成 → 主动回调(
app.antispam.active.callback.api)或客户端轮询http-api查询。 dubbo-provider:对内提供媒体任务的 Dubbo 读写服务。
二、可部署服务清单
| 部署单元目录 | artifactId | 镜像名 | 端口 | 服务类型 | 独立 Dockerfile | 是否进 kubernetes.yml |
|---|---|---|---|---|---|---|
facade/dubbo-provider | antispam-media-solution-facade-dubbo-provider | antispam-media-solution-dubbo-provider | Dubbo 协议端口(默认) | Dubbo Provider | 有 | 模块根未发现 kubernetes.yml |
facade/http-api | antispam-media-solution-facade-http-api | antispam-media-solution-http-api | 18187(private 覆写 8080) | HTTP(查询 / 回调 / 反馈) | 有 | 同上(未发现) |
facade/http-check-api | antispam-media-solution-facade-http-check-api | antispam-media-solution-http-check-api | 18186(private 覆写 8080) | HTTP(同步/异步提交受理) | 有 | 同上(未发现) |
scheduler | antispam-media-solution-scheduler | antispam-media-solution-scheduler | 无 | ElasticJob 定时任务 | 有 | 同上(未发现) |
storage | antispam-media-solution-storage | antispam-media-solution-storage | 无 | Kafka Consumer(结果入库/归档) | 有 | 同上(未发现) |
console/api | antispam-media-solution-console-api | — | 8080 | 控制台 HTTP | 无(不构建) | 否 |
- 模块根目录未发现
kubernetes.yml,K8s 清单由外部(Kustomize/平台侧)维护,本文无法据此核对 Deployment 数量。 <finalName>=${project.artifactId}(非${artifactId}-${version}-application),因此 Dockerfile 的COPY ./target/${APP_NAME}.jar与产物名一致。
三、同模块启动顺序
storage—— 先把结果入库/归档通路就绪,防止提交后结果无处落库。http-check-api—— 打开受理入口,但此时提交仅登记、下游 Worker 未开闸,可安全灰度。scheduler—— 启动后mediaDataSubmitWorker立即开始扫描并分发任务,须确保各业务引擎已就绪。http-api—— 打开查询与回调面;存储链路已通,客户查询可返回一致数据。dubbo-provider—— 最后注册内部 Dubbo 服务,供其它模块跨模块调用。
四、逐服务启动逻辑
facade/dubbo-provider
- 启动类:
com.netease.is.antispam.mediasolution.facade.dubbo.DubboApplication。 @SpringBootApplication(无 exclude)。@Enable*/@Import:@EnableDubboAutoConfiguration(@Import(DubboConfiguration.class))、@EnableAspectJAutoProxy、@EnableCdcDataSubscribe、@EnableBusinessClient、@EnableRecoverComponent。无@EnableApolloConfig。- 组件扫描:
DubboConfiguration覆盖service、kafka、manager、components.callback、redis、logic、bill、facade.dubbo.health、component.es、component.kafka,并以basePackageClasses=ProductConfigService兜底;同时@MapperScan。dubbo.scan.basePackages=...facade.dubbo。 - 数据源:无需 Exclude,说明该单元按需从组件引入数据源配置。
main()无自定义;启动钩子:未发现。
facade/http-api
- 启动类:
com.netease.is.antispam.mediasolution.facade.http.HttpApplication。 @SpringBootApplication(无 exclude)+@EnableAspectJAutoProxy、@EnableFacadeAutoConfiguration(→@Import(FacadeHttpConfiguration))、@EnableCdcDataSubscribe、@EnableBusinessClient、@EnableRecoverComponent、@EnableI18nComponent、@EnableApolloConfig。- 组件扫描:
facade.http.configuration.FacadeHttpConfiguration(@ComponentScan:facade.http.controller、kafka、redis、integration、service、manager、components.callback、component.es、component.kafka、helper、bill、oss,basePackageClasses={MediaCallbackHandler, LogicScanMarker}+@MapperScan(...dao))。 - Kafka:producer only;
media.callback.concurrency.control.enable=true。 - 配置:
server.port=18187(private 覆写 8080);app.id=antispam-media-common,Apollo 命名空间application。 - 启动钩子:未发现。
facade/http-check-api
- 启动类:
com.netease.is.antispam.mediasolution.facade.http.check.HttpCheckApplication。 @SpringBootApplication(exclude = {DataSourceTransactionManagerAutoConfiguration, HibernateJpaAutoConfiguration, DruidDataSourceAutoConfigure, DataSourceAutoConfiguration})—— 4 个数据源自动配置全关。@Enable*:@EnableAspectJAutoProxy(exposeProxy = true)、@EnableBusinessClient、@EnableI18nComponent、@EnableApolloConfig。- 组件扫描:
EnableFacadeAutoConfiguration→@Import(FacadeHttpConfiguration),其@ComponentScan含facade.http.check.controller、monitor、apollo,basePackageClasses={TextSubmitter, SubmitRateLimiter, ProductConfigService, LogicScanMarker}。 - 该
FacadeHttpConfiguration内含静态类WithDatabase:@ConditionalOnProperty(name="spring.datasource.url")→ 只有配置了spring.datasource.url时才@ImportAutoConfiguration({DataSourceAutoConfiguration, DataSourceTransactionManagerAutoConfiguration, HibernateJpaAutoConfiguration, DruidDataSourceAutoConfigure})+@MapperScan+@ComponentScan({MediaSolutionServiceImpl, MediaSolutionManager})。 - 配置:
server.port=18186;app.id=antispam-media-solution,Apollo 命名空间application,application.yml。 - 启动钩子:未发现。
scheduler
- 启动类:
com.netease.is.antispam.mediasolution.scheduler.SchedulerApplication。 @SpringBootApplication+@EnableSchedulerAutoConfiguration(→SchedulerConfiguration)、@EnableScheduling、@EnableElasticJob、@EnableCdcDataSubscribe、@EnableOssClient、@EnableBusinessClient、@EnableFileParser、@EnableRecoverComponent、@EnableAspectJAutoProxy(exposeProxy=true)、@EnableApolloConfig。- 组件扫描:
SchedulerConfiguration覆盖kafka、redis、integration、service、manager、components.callback、component.es、reconciliation、component.kafka、bill、monitor、apollo。 - 影子库:
@Bean tableNameReplaceFilter=com.netease.is.shadow.client.db.TableNameReplaceFilter。 - ElasticJob 作业:
audioVideoCensorDataWorker(0 0/20)、mediaDataSubmitWorker(0 0/10)、mediaSolutionunCheckWorker(0 */2)、archiveDataCleanWorker、mediaBillRecoverWorker、mediaDataLockRecordReleaseWorker、mediaCallbackRedisCleanWorker、mediaActiveCallbackErrorWorker、bookParseWorker/bookChapterSubmitWorker/bookParseCheckingWorker、productOfflineArchiveDataCleanWorker;online 另启mediaSolutionDataShadowSubmitWorker、dataConsistencyWorker、mediaSolutionCheckingWorker等。 - 配置:
app.id=antispam-media-solution;ElasticJob ZK namespacenetease-antispam-mediasolution-job。 - 启动钩子:
scheduler.YidunQosApplication。
storage
- 启动类:
com.netease.is.antispam.mediasolution.storage.StorageApplication。 @SkipCodeCoverage+@SpringBootApplication+@EnableStorageAutoConfiguration(→@Import(StorageConfiguration))、@EnableScheduling、@EnableDistributeId、@EnableCdcDataSubscribe、@EnableBusinessClient、@EnableRecoverComponent、@EnableApolloConfig。- 组件扫描:
StorageConfiguration(@ComponentScan含storage.consumer.health、reconciliation、oss+@MapperScan);注入tableNameReplaceFilter(影子库)。 - 配置:
app.id=antispam-media-common,Apollo 命名空间application。 - 启动钩子:
storage.YidunQosApplication。
五、启动前置依赖
| 依赖 | 配置键 / 地址 | 阻塞 or 弱依赖 | 配置文件 |
|---|---|---|---|
| Apollo | 无显式 meta;app.id(antispam-media-common / antispam-media-solution)、apollo.bootstrap.namespaces | 弱 | application.properties |
| ZooKeeper(Dubbo) | dubbo.registry.address=zookeeper://zk-0/1/2.zookeeper.yidun-infra:2181 | 阻塞 | application-private.properties |
| ZooKeeper(business client) | business.client.options.zookeeper.rootPath=/netease-antispam/online/config | 阻塞 | application-*.properties |
| Redis Sentinel | spring.redis.sentinel.nodes(private) | 阻塞 | application-private.properties |
| TiDB | spring.datasource.url(hikari maximum-pool-size=10) | 阻塞 | application-private.properties |
| Kafka | produce cluster jd(private) / main(online);topic Antispam_MediaSolution_Msg、..._Top_Msg、..._Callback_Msg、Antispam_Media_Finish_Msg、Antispam_Media_ES_EVENT_MSG、Antispam_Media_Feedback_Msg、Antispam_Bill_TrialStat | 阻塞 | application-*.properties |
| Elasticsearch(归档) | http://elasticsearch-yidun-master.yidun-infra.svc:9200;private 的 elasticsearch.cluster.servers=xxx 为占位符 | 阻塞 | application-*.properties |
| OSS | 走 Apollo 下发 | 弱 | — |
| 下游业务引擎 HTTP | app.antispam.text/image/audio/video/file/videosolution.check.api;app.antispam.active.callback.api=http://antispam-media-solution-http-api.yidun.svc:8080/v1/mediasolution/active/callback | 阻塞(提交链路) | application-private.properties |
六、启动参数与 Profile
- Spring profiles:容器统一
-Dspring.profiles.active=private。 - Maven profile:
default、test、online、private、jiande-online(部分单元含xjp-online、singapore-online、pre)。 - JAVA_OPTS:
http-api/dubbo-provider/http-check-api=-Xmx512m -Xms512m -XX:+UseG1GC -Dspring.profiles.active=private;scheduler/storage=-Xmx1024m -Xms1024m+ 同款 GC/Profile。 - base image 与仓库:
FROM private-registry.yidun.internal/yidun/base-image:jdk17;推送仓库private-registry.yidun.internal/yidun;tagmigu-231016(build.sh)—— 注意与常见1.0.0.private不同。 - 构建:
buildAll.sh→mvn clean install -Pprivate→ 遍历build.sh→docker build+sudo docker push→podupdate.sh。 - ElasticJob ZK namespace 固定
netease-antispam-mediasolution-job。
七、启动期踩坑
- 模块根无
kubernetes.yml:本模块的部署编排不在仓库内,核对副本数/探针需另找清单来源。 http-check-apiprivate 的elasticsearch.cluster.servers=xxx是占位符:直接跑会指向非法地址,需依赖 Apollo 覆盖或本地改配置。http-check-api关掉 4 个数据源自动配置:当spring.datasource.url未配置时,WithDatabase静态类不生效,任何依赖 Mapper 的 Bean 会抛NoSuchBeanDefinitionException。dubbo-provider完全不接 Apollo:无@EnableApolloConfig,改配置必须重打镜像。scheduler与storage都注册TableNameReplaceFilter(影子库):缺少 shadow 组件依赖或配置时会启动异常。- Dubbo group 各服务/各 profile 不一致:private 下
http-check-api为/yidun/jiande-online/dubbo,而dubbo-provider/http-api/scheduler/storage为/yidun/antispam/online-new/yidun-antispam-dubbo—— 跨服务调用若 group 对不上,会「注册成功但发现不到」。 http-check-api与scheduler共用app.id=antispam-media-solution:命名空间相同,配置误改会同时影响两者。storage使用@EnableScheduling+@EnableDistributeId:既跑本地定时又依赖分布式 ID,分布式 ID 的 ZK/命名空间必须就绪。
八、跨模块前置
- 下游各业务检测引擎:文本、图片、音频、视频、文件、视频解决方案的检测 HTTP/ Dubbo 接口必须先可用,否则
scheduler分发即失败。 - 自身回调地址可达:
antispam-media-solution-http-api.yidun.svc:8080需在集群内可解析(主动回调闭环)。 - 共享基础设施:Kafka、ZooKeeper、Redis Sentinel、TiDB、Elasticsearch 由平台统一提供,需先启动。
- 公共配置:Apollo 的
application/application.yml命名空间由平台预置。