对 holoread 项目的思考

大概从去年六月,我开始负责名为 holoread 的项目开发,距今已有半年之多。上线也有一阵子了,最近刚好不是特别忙,负责 iOS 开发的同学已经离职,项目估计也要凉了,谈谈对项目本身的思考吧。

技术体系

先说说技术体系:

  • 负责爬虫同学用 python 爬取各家新闻媒体聚合,再进行训练聚类去重等,写入 mongo 数据库。
  • 我这里用 node.js 定时读数据库,用 cheerio 等框架进行文本处理,英文的内容使用 sougou 接口进行翻译,处理完毕后写入另一个 mongo。
  • 业务层使用 golang 的 gin mgo 等框架做 api 服务,vue.js 写的后台管理系统,websocket 实现一个简单的协同编辑。
  • 部署使用交叉编译的方式,打包成二进制文件,发送到服务器端,supervisorctl 启动服务。

并发

先铺垫一下术语说明:

QPS (queries per second) = req/sec = 请求数/秒【QPS计算PV和机器的方式】

QPS统计方式 [一般使用 http_load 进行统计]
QPS = 总请求数 / ( 进程总数 * 请求时间 )
QPS: 单个进程每秒请求服务器的成功次数

单台服务器每天PV计算
公式1:每天总PV = QPS 3600 6
公式2:每天总PV = QPS 3600 8

服务器计算
服务器数量 = ceil( 每天总PV / 单台服务器每天总PV )

【峰值QPS和机器计算公式】
原理:每天80%的访问集中在20%的时间里,这20%时间叫做峰值时间
公式:( 总PV数 80% ) / ( 每天秒数 20% ) = 峰值时间每秒请求数(QPS)
机器:峰值时间每秒QPS / 单台机器的QPS = 需要的机器

问:每天300w PV 的在单台机器上,这台机器需要多少QPS?
答:( 3000000 0.8 ) / (86400 0.2 ) = 139 (QPS)
问:如果一台机器的QPS是58,需要几台机器来支持?
答:139 / 58 = 3

目前的业务大约有 200w 条数据(增量型),日均1w 左右吧。 我们这里使用一台 4核8G 2.0HZ 的普通境外服务器,应对目前流量没什么问题。
nginx 和 linux 进行了参数优化(TCP/IP参数配置, 最大文件描述符等等),使用 wrk 对 api 进行下压力测试:

$ ./wrk -t 4 -c 1000 -d 60 --latency --timeout 5s xxx
Running 1m test @ xxx
  4 threads and 1000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   593.05ms  750.50ms   5.00s    87.29%
    Req/Sec   291.34    111.96     0.88k    72.42%
  Latency Distribution
     50%  211.44ms
     75%  676.19ms
     90%    1.57s
     99%    3.68s
  67888 requests in 1.00m,61.95MB read
  Socket errors: connect 0,read 0,write 0,timeout 1258
Requests/sec:   1130.38
Transfer/sec:      1.03MB

在当前条件下 (4线程,1000连接数,一分钟请求),结果大约为 1200 左右的 QPS,算是及格了,还有提升的空间。
如果服务器迁回国内, 访问速度会有明显提升。还有就是用上 HTTP/2 等技术。

websocket 服务器扩容

websocket 业务如果扩大,就应该独立出来了。业务服务器和 websocket 服务器独立运行。在参考了一些优秀设计之后, 我想出一个注册中心的方案,具体设计如下图。 不足之处,还望指正。

多机 websocket 设计

另外的方案还有redis发布/订阅等,首先,让用户在普通的http请求里登录,然后把登录的session存到redis里,让登录信息分布式。因为每次连接websocket时都会先发一个普通的http请求,然后upgradewebsocket的,这个时候,登录的cookie是存在登录的key的,因为在websocketopen阶段是能读到这个cookie信息的,把这个去 redi 查找下即可。

数据处理

目前数据以每日 10000条增长,过往数据没有价值, 可以在 mongo 中设置过期时间。 其他的数据库优化手段基本是 合理索引和查询,延时集中写入,读写分离等。

微服务管理 / 监控

酝酿中…

部署 / CI

酝酿中…

总结

由于项目本身定位的原因以及其他因素, 导致这个项目属于半玩票,所以高并发的场景只是假设和模拟了, 在公司的渣渣网络(不稳定)环境下,并发测试花了今天不少时间😂。目前的微服务基本靠人工线上管理监控, 部署是直接 scp 传文件, 有些太过暴力, 希望在接下来的两篇文章中, 总结出一些经验和改善措施。

参考:

使用ab和wrk对OSS进行benchmark测试
websocket多台服务器之间怎么共享websocketSession?
Nginx高并发下的优化