原项目仓库:https://gitee.com/novel_dev_team/novel-cloud
汇报ppt演示:https://docs.qq.com/slide/DZGFhdkRpaGJRbVJP
项目背景:
小说网站没有商城系统那种复杂的业务。但是作为互联网项目,一样需要面对大规模用户和海量数据的处理,所以高并发、高可用、高性能、高容错、可扩展性、可维护性也是小说网站设计需要考虑的问题,商城系统中所用到的技术同样适用于小说网站。综上所述,使用微服务架构来构建一个小说门户平台是非常有必要的。
软件架构:
项目面向 APP、小程序、浏览器三端用户,整体采用 Docker 容器加上 K8s 云原生微服务架构。整个架构分成五层:客户端接入层、Docker 微服务集群层、基础公共服务层、存储中间件高可用集群,还有 CI/CD 自动化交付流水线。
整体数据流是:客户端发起请求,经过 CDN、Nginx 负载均衡,到达认证网关集群,再转发给各个业务微服务,最后操作底层存储中间件。开发和运维通过流水线完成自动化发布。

第一部分:客户端与互联网接入层
客户端包含 APP、小程序、浏览器。用户请求先经过互联网 CDN。CDN 主要缓存图片、页面这类静态资源,把资源下沉到边缘节点,减少用户访问延迟,同时减轻后端服务器带宽压力。动态接口请求会透传给后端的 Nginx。
我们部署了两组 Nginx 负载均衡。一组专门处理静态资源回源请求;另一组处理动态 API 请求,做 SSL 证书卸载、IP 黑名单、预处理限流,再把流量转发到后端的网关集群。
第二部分:Docker 微服务集群
接下来是核心的 Docker 微服务集群,这块分为三块:接入网关集群、业务微服务、底层基础设施组件。
- 先说认证网关集群。 所有客户端的接口请求,全部都要经过网关集群,它是整个微服务的唯一出入口。网关基于 Spring Cloud Gateway,跑在 Docker 容器上,K8s 统一调度。我们部署多组网关接入服务,多副本 Pod 运行,实现高可用,还可以做流量隔离,APP、小程序、浏览器流量可以分到不同网关组。就算某一个端遭遇爬虫攻击,也不会影响其他业务。
网关分为两大模块,API 网关和认证限流过滤器。 API 网关主要做路由转发,根据 URL 路径把请求转发给对应的业务微服务,路由规则全部放在 Nacos 配置中心,可以动态修改,不用重启网关。同时处理跨域、链路追踪日志,借助 Nacos 服务发现,通过服务名调用后端服务,不用写死 IP 地址。
认证限流是网关内部的过滤器,请求还没到业务服务就先执行这套逻辑。第一做身份认证,对接全局认证服务,拿到请求头的 JWT 令牌,优先从 Redis 哨兵缓存校验 token,减少远程调用。token 合法,就把用户 ID、角色信息传递给下游服务;token 无效直接返回 401,请求不转发后端。第二做权限校验,在网关层就拦截没有权限的访问。第三集成 Sentinel 做限流熔断,可以按接口、用户 ID、客户端渠道限流,流量直接在网关拦截;下游服务故障直接熔断返回兜底,防止雪崩,同时支持 IP 黑名单拦截爬虫。
完整请求流程:用户请求经过 CDN、Nginx 负载均衡,分发到网关各个 Pod。依次经过黑名单、token 认证、权限校验、限流熔断,全部校验通过,才转发业务微服务,任意一步失败直接终止请求。
网关依赖 Nacos 管理路由规则,Redis 哨兵缓存会话,Sentinel 管控流量,监控服务做告警。多副本部署消除单点故障,流量大的时候直接扩容副本提升性能。 - 接下来讲业务微服务。 我们按照业务域垂直拆分微服务,全部以 RESTful API 对外提供接口,每个服务独立 Docker 部署,可以单独发布扩缩容,互不影响。 包含首页微服务,负责首页榜单推荐;会员微服务处理账号登录、会员信息;小说微服务做书籍阅读、书架;作家微服务管理作家稿件、稿费;支付微服务处理订单、支付退款;文件微服务对接 OSS 处理文件上传;新闻微服务处理资讯;搜索微服务对接 ES 做全文检索。
- 然后是微服务基础设施组件。 Nacos,分为注册中心和配置中心。注册中心负责所有服务注册发现,服务启动自动上报实例地址,自动剔除故障节点;配置中心统一管理各个环境配置,配置变更实时推送到各个服务,不用重启。 Feign 是声明式远程调用,简化微服务之间接口调用;Ribbon 做客户端负载均衡;Sentinel 负责全链路的限流、熔断、降级,保障服务稳定性。
第三部分:基础服务
为整个集群提供公共能力。
- MQ 服务,基于 RabbitMQ,用来异步解耦。像订单处理、稿费计算、消息通知全部异步处理,削峰填谷,高并发的时候保护数据库。
- TASK 任务服务,分布式定时任务,处理榜单统计、会员过期、稿费结算,保证任务不会重复执行。
- 认证服务,统一账号体系,颁发 JWT 令牌,管理用户角色权限,给网关和业务服务提供鉴权能力。
- 监控服务(zabbix),采集容器、服务、中间件全部指标,链路追踪,出现故障通过钉钉告警。
第四部分:存储中间件集群
- 首先是 MySQL MHA 高可用集群
MHA 由 MHA‑Manager 管理节点,加上一主多从 MySQL 节点组成。 主库承担写操作,多个从库做读,实现读写分离,分担数据库压力。
MHA Manager 会持续检测 MySQL 节点状态,检测 SSH 连通性,执行 select 1 探测实例存活,同时监控主从复制状态。 如果主库发生宕机,MHA 自动执行故障转移:选出数据最完整的从库提升为新主库,其余从库同步指向新主。
切换完成之后,执行 MHA 自定义钩子脚本。脚本调用 Nacos 的 OpenAPI,更新 Nacos 里面 MySQL 主库的连接配置。同时zabbix调用钉钉机器人 webhook 发送钉钉告警,通知运维主库已经切换。 - Redis 哨兵集群
架构是 1 主、2从,3 个奇数的哨兵节点。 Redis 用来缓存热点数据,比如小说章节、首页榜单、用户 token,大量减少 MySQL 查询压力。
哨兵具备监控、自动故障转移、通知三大能力。持续监控主从节点状态,如果主 Redis 宕机,哨兵集群投票选出新的主节点,其余从节点跟随新主,切换完成推送告警通知。
业务连接地址维护在 Nacos,切换之后更新配置,应用动态刷新连接。读写分离,写走主节点,读请求分发到从节点,支撑高并发缓存查询。 - 其他配套中间件:RabbitMQ 集群做消息队列;ElasticSearch 负责全文检索,分担 MySQL 查询压力;阿里云 OSS 存储图片、附件文件。
第五部分:CI/CD 流水线
CI/CD 云原生交付流水线,基于 Docker 和 K8s。 开发人员写完代码提交到 Github,自动构建 Docker 镜像,推送到私有镜像仓库。Kubernetes API 调度集群,拉取镜像运行容器。K8s 可以实现容器自愈、弹性扩缩容、滚动更新,发布服务不停机。 运维这边,通过 Jenkins Pipeline 流水线做发布、灰度、回滚操作。整个开发运维两条流水线,实现自动化发布上线。
架构整体优势:
整套架构优势:第一分层解耦,各个模块独立迭代;第二多层高可用,应用层 K8s 多副本,数据库 MHA、Redis 哨兵消除单点;第三高并发,CDN 加速、缓存、MQ 削峰、读写分离支撑大量用户;第四云原生自动化运维;第五全链路限流熔断,防止系统雪崩。
遇到的问题和解决方案:
- 第一是 MySQL MHA 主从切换问题:
主库宕机自动切换后业务无法自动切换新主库,我们通过 MHA 钩子脚本调用 Nacos 更新数据库地址,代码监听配置变更自动重建数据源。同时考虑到 MHA 管理节点宕机无告警的隐患,我们做了三层告警兜底,MHA 切换通知、定时巡检脚本、Zabbix 指标监控,异常全部钉钉推送,保证故障及时发现。
- 第二是高并发压力问题:
小说首页、章节查询量巨大,频繁查询 MySQL 造成压力过高。我们采用 Redis 缓存热点数据,MySQL 读写分离,全文检索交给 ES;点赞、阅读量这类瞬时高并发操作通过 MQ 异步处理,削峰保护数据库。
- 第三是CI/CD 发布问题:
早期全靠手动部署,容易操作失误,我们搭建 Jenkins 流水线实现自动化打包发布,支持灰度和一键回滚。同时把所有环境配置统一放到 Nacos,按环境隔离,避免线上测试配置混淆引发故障。
- 第四是MySQL 全量备份时间长,备份过程消耗 IO,影响线上读性能问题:
不在主库备份,统一在从库执行全量备份,规避影响主库读写,拆分备份任务,错峰凌晨低流量执行,备份限速,限制 IO 读写占用比例
- 第五是CDN 回源频繁,带宽成本过高:
调整静态资源缓存过期时间,延长缓存周期;对不常变动图片、资源设置长期缓存,减少回源请求,降低带宽开销。
微服务项目结构:


项目地址(首页):

账号管理(novel-user):

基于Spring Boot Admin 构建的微服务监控中心:


服务发现和配置管理:
http://192.168.20.100:8848/nacos

登录 Kibana,执行小说索引创建语句:
http://192.168.20.100:5601/app/dev_tools

登录 xxl-job 控制台(分布式任务调度平台),执行任务导入 MySQL 中的小说数据到 Elasticsearch:
http://192.168.20.100:8080/xxl-job-admin

ES全文搜索(novel-search):
