千万流量项目总结

春节参加某Q活动,支持千万级流量。


千万流量项目总结_第1张图片
系统简要架构(未包括高可用).png

优化的过程:

根据压测报告和日志分析,不断优化性能短板。

现将本次项目所做的优化点列出来:

1.tomcat连接池

  • 设置最大线程数maxThreads,2000 (IO密集型应用) 从linux角度某用户最大线程的限制65530
    从jvm角度启动最大线程设置 12G/1M = 12288
    最大线程数的配置绝对不是越大越好, cpu在线程切换时消耗的时间随着线程数量的增加越来越大,单次请求的响应时间也会急剧的增加。
    最好的做法是:在不断测试的基础上,不断调整、优化,才能得到最合理的配置。


    千万流量项目总结_第2张图片
    线程池计算公式.png

最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目。
线程等待时间(一般指IO等待时间)所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。

  • 设置最大连接数maxConnections,10000
    如果设的较小,可以保证接受的请求较快相应,但是超出的请求可能就直接被拒绝或者排队中。
    如果设的较大,可能就会出现大量的请求超时的情况,因为我们系统的处理能力是一定的。

  • 设置最大排队数acceptCount,5000
    Tomcat一旦达到了maxConnections,Linux仍然可以接受acceptCount的设置.(就是TCP三次握手完成还没有被应用accept走的socket队列大小。)
    可以增加系统的处理容量,但并不会增加tps

2.DB优化(获取连接慢)

  • 优化sql,不存在join,or , select出来字段是所需要的字段.
  • 优化索引,让每条select都走索引
  • 设置连接池的最大连接数,设置的10000/14 = 700, (10000为项目使用的mysql最大连接数,14为机器数)
  • 尝试测试不同的连接池,选择性能最佳的,选择的hikari
  • 不使用数据库事务,因为数据库操作代码都在消费者中,在代码中做幂等性.


    千万流量项目总结_第3张图片
    数据库连接池测试.png

注:查询一条语句性能测试(ms)

3.redis优化

  • redis存储数据结构
    将db中的数据load保存为redis的hash结构(全表保存) 根据业务优化redis存储结构,减少redis查询次数(例如将phone和券code的领取状态单独存储)
  • 热点key的处理
    redis cpu为单核,进行分片处理
    大量查询会成为严重短板,通过hash值进行分片处理,使之近似均匀,
    redis能够承受的量是之前的3倍.
  • 设置redis最大连接数
    3*10000/14 = 2100


    千万流量项目总结_第4张图片
    redis cpu监控图.jpg

4.mq优化

  • 消息体一般为redis key,可以去redis拿取数据,优化消息存储大小
  • 可以按功能不同,拆分多个队列,加快单逻辑处理速度
    目前根据业务拆分为5个队列

5.加快消费者消费速度

  • 增加消费者数量,20个
    根据下游(DB,业务方)TPS多次测试得出,可以利用消费者数量控制下游的负载
  • 增加消费者预读取数据数量,50个
    减少网络请求次数
  • 优化消费逻辑
    完善幂等操作(解决消息重复消费问题),db操作,业务查询操作

5.java启动脚本优化

  • 设置最大内存为系统的3/4
  • 使用G1垃圾回收器,参考RocketMQ启动脚本


    千万流量项目总结_第5张图片
    RocketMQ启动脚本.jpg

6.多台可能和单台tps/消费者消费速度 差不多

  • 连接池问题,tomcat连接池,数据库连接池,redis连接池…
  • 资源锁的问题,3种方式,我们采用redis控制.

7.http连接

  • TCP并发链接(没有及时释放),CLOSE_WAIT过多。
  • 设置连接池最大连接数量1000

8.项目初始化

  • 将数据库数据先load到redis。可以控制速度,百万数据大概5min load完。

9.日志优化(通过日志分析不出来)

  • 异步写日志文件
  • 减少日志打印,例如正常请求仅打印入参和出参
  • kafka+ELK

你可能感兴趣的:(千万流量项目总结)