你在项目中遇到了哪些困难,怎么去解决的?
1、业务上的问题:
1.针对点赞系统进行优化。
之前系统存在问题,为什么要优化他。之前我们实现的是用户的点赞行为直接调用接口,然后将点赞信息进行落库操作,插入到MySQL中,中间不会存在缓存层,就导致如果高并发的情况下,数据库的压力是很大的。
解决方案:
-
1.可以是用RocketMQ消息队列进行削峰处理。当初想到的是这个方案,但是如果高并发出来,会导致数据挤压,用户点赞的消息也会出现延迟显示,那想办法解决掉这个积压的问题,那就会出现跟初始情况一样的问题了,数据库压力还是很大。
-
2.那让移动端那边做缓存呢?用户点赞行为通过一个随机值,用来判断要不要请求接口发送数据给服务端进行落库操作,但是这个方案明显把服务端跟移动端的耦合度明显提升了很多,而且已经发版的移动端需要进行热修复等问题,周期太长,优化繁琐,成本太高,就舍弃了。
-
3.使用Redis做缓存缓冲层,将用户ID,点赞文段ID,类型作为Key,然后status,activeTime作为值,这样既保证了重复点赞的问题,也保证了查询点赞时候的零延迟问题,可以通过查询这个缓存中的key,就能得知当前点赞行为是否需要发送统计信息到点赞统计中来。
通过对以上三种方案的利弊选择,我们最终选择了方案3.
---巴拉巴拉----先不说了
2.针对关注页系统进行优化。
3.保证消息的零丢失方案。
2、技术上的问题:
1.高考限流方案
性能瓶颈定位的核心: 参数总结: PTS 优势: 初步方案: 数据隔离问题: 总结: 性能瓶颈定位的核心: 在前面频繁地提到了性能指标,那性能指标究竟有哪些,我们在性能测试的过程中需要重点关注哪些指标项呢?
从维度上划分,性能指标主要分为两大类,分别是业务性能指标和系统资源性能指标。
业务性能指标可以直观地反映被测系统的实际性能状况,常用的指标项有:
并发用户数 事务吞吐率(TPS/RPS) 事务平均响应时间 事务成功率 而系统资源性能指标,主要是反映整个系统环境的硬件资源使用情况,常用的指标包括:
服务器:CPU利用率、处理器队列长度、内存利用率、内存交换页面数、磁盘IO状态、网卡带宽使用情况等; 数据库:数据库连接数、数据库读写响应时长、数据库读写吞吐量等; 网络:网络吞吐量、网络带宽、网络缓冲池大小; 缓存(Redis):静态资源缓存命中率、动态数据缓存命中率、缓存吞吐量等; 测试设备(压力发生器):CPU利用率、处理器队列长度、内存利用率、内存交换页面数、磁盘IO状态、网卡带宽使用情况等。 Response Time: RT
互联网行业标准是500ms 内,我们要求是99% 1s内,1%2s 内。
系统处理能:
定义及解释
系统处理能力是指系统在利用系统硬件平台和软件平台进行信息处理的能力。 系统处理能力通过系统每秒钟能够处理的交易数量来评价,交易有两种理解:一是业务人员角度的一笔业务过程;二是系统角度的一次交易申请和响应过程。
前者称为业务交易过程,后者称为事务。两种交易指标都可以评价应用系统的处理能力。一般的建议与系统交易日志保持一致,以便于统计业务量或者交易量。系统处理能力指标是技术测试活动中重要指标。
互联网中型网站:1000TPS~50000TPS 我们网站目前最大2000TPS,压测是3000-4000TPS 并发用户:
压测最大可以承受100w-2000w并发用户。
3.在3000-4000TPS 120-200W 用戶 测试各个服务部署机器的cup,io,内存的使用情况都保持在70%左右,
并发用户在1w-2w之间测试。
二 需要梳理核心业务场景,比如高考高频操作(搜索,推荐页 banner,模拟用户搜索,模拟用户阅读)
参数总结: Response Time: 99% 1s内,1%2s 内。 TPS: 目前是2000,压测4000-6000TPS 用户并发数:120w 到200w 高频的qps:5000-8000 测试各个服务部署机器的cup,io,内存的使用情况都保持在70%左右 PTS 优势: 环境:可选择已购买的ECS、RDS、SLB作为测试机使用。 脚本:脚本是执行性能测试的基础,脚本里包括需要压测的服务器地址、压测的url、压测的参数和压测的类型。 场景:场景需要绑定脚本来运行,一个场景绑定一个脚本,可在场景中设置并发压测用户数、施压模式。 任务:任务执行需要绑定场景,一个任务可以绑定多个场景,任务开始执行后可以实时查看性能指标。 结果:结果自动保存可随时查看
高级设置,全链路压测的话可以监控各个服务链路。
初步方案: 测试需要梳理根据业务场景梳理用户常用的接口,并形成用例(然后根据预估的参数进行压测) 基哥准备阿里pts及独立的数据库,redis里(需要考虑只测试读,写情况根据场景尽量不写入hbase和redis) 服务端开发在测试写需要关闭hbase、es的写入。 如果发现接口瓶颈需要接入限流接口并进行测试。
数据隔离问题: 读请求压测,产生的行为数据进入hbase,或者其他数据写入redis 写请求压测,数据库,redis,es,hbase 产生的脏数据 是独立一套环境还是代码中隔离(权衡成本)
总结: 1.测试需要梳理高并发应用场景:比如高考肯定搜索,或者高考推荐相关场景流量比较大,这部分需要重点压测
2.开发人员需要注意慢sql,先从业务角度去优化这条sql。如果数据量大,可以考虑分库分表
3.高考期间肯定是读多写少,为节约成本,尽量压测高流量的读场景用例,要解决产生的读记录。
4.如果压测运用的比较成熟的话,可以升级发布流程,现在使用的蓝绿发布,灰度环境很浪费资源。以后压测,测试充分就可以采用AB滚动发布,为公司节约成本。
参考:
全链路压测
1.全链路压测: 压测一般分4步骤: 1.业务流量预估阶段: 2.系统容量评估阶段: 3.容量的精调阶段 4.流量控制阶段 工作安排: 1.第一阶段: 简单测试qps阶段 2.第二阶段:模拟真实用户行为阶段 3.第三阶段:用真实用户测试,精细化流量控制达到压测效果(service mesh) 总结: 1.全链路压测: 压测一般分4步骤: 业务流量预估阶段:通过历史数据分析未来某一个时间点业务的访问量会有多大;
系统容量评估阶段:初步计算每一个系统需要分配多少机器;
容量的精调阶段:通过全链路压测来模拟高考时刻的用户行为,在验证站点能力的同时对整个站点的容量水位进行精细调整;
流量控制阶段:对系统配置限流阈值等系统保护措施,防止实际的业务流量超过预估业务流量的情况下,系统无法提供正常服务。
1.业务流量预估阶段: 因为去年高考没有具体的dau,或者最大qps,所以只能根据目前的日活和qps 预测,现在50w的DAU,所以预测高考的55w-80w的日活,现在50w,阿里的qps 是1000(感觉有点低),所以只要抗住3000-5000qps 就可以了。
2.系统容量评估阶段: 网关层:zuul 独立部署3台,测试需要每台扛过1500-3000qps并发,可以用wrk高性能压测。
,具体的某个接口可以用jmter或者ab测试。纸条服务正式环境是6台,每台每个接口抗住500-1000的qps,特别是慢sql接口,及核心接口。
3.容量的精调阶段 这个是比较难的压测,而且需要监控,是否可以用阿里的全链路压测。优点是有成熟的方案,监控及报警,自己去做的话需要看日志,监控好像没有直观的监控,可以上链路追踪查看问题。
4.流量控制阶段 1.网关层通过 信号量限流。
2.服务层通过令牌桶令牌数量去控制,可以调整令牌数达到限流的目的。
3.分层压测,分层控制,从openRestry--》zuul—》各个服务的核心接口限流。
4.借助开源代码github.com/zyanycall/s… 进行压测。
工作安排: 1.第一阶段: 简单测试qps阶段 对每个服务单独单机阶段(工具使用ab压测,wrk压测) 对集群压测(jmter、wrk 工具) 具体工作安排:
服务端开发人员或者测试人员现在本地使用ab 或者jmter压测,提供参考线上qps一个指标和url地址 然后根据测试环境和url 对线上进行压测。 评估服务器服务实例个数 进行一个总的压测达到期望qps 2.第二阶段:模拟真实用户行为阶段 方案一:需要一套独立测试库,es,redis 这样不用考虑脏数据的问题 (开发成本低,经费比较高) 方案二:需要在业务代码加入标识,然后通过代码逻辑把脏数据路由到库中,测试完删除(开发成本高,不需要经费) 具体工作安排:
方案一 根据阶段一的容器实例及qps模拟70w-100w真实用户请求,需要独立数据库,es,redis 数据迁移(运维实施困难)
方案二 需要加入标识用户,然后把标识用户数据删除或者路由到另一套数据库,es,redis hbase(服务端开发人员改动比较大)
3.第三阶段:用真实用户测试,精细化流量控制达到压测效果(service mesh) k8s+istio istio能精准的控制流量到哪台服务器,而且可视化界面,通过调整流量可以看到每个服务的压力,这样真实的场景能大约了解到服务的性能,需要k8s环境,需要配置istio)
总结: 1.目前阶段我们可以准备第一阶段,了解ab wrk 高级测试用法,这样能大概知道每台服务器的qps
2.第二阶段需要准备时间久而且如果要实现可持续性压测的话,必须要有一套压测系统,开发成本高,时间久。是否可以直接考虑第三阶段
- 精细化流量控制阶段,由于我们的用户还算比较稳定不会像电商有促销活动,每次突增用户有限,方案3不仅能压测,而且在用户突然增加后设置预警,然后添加机器 是比较推荐的一种方法
高考限流方案(令牌桶算法)
由于高考我们的系统会突然增大,所以需要考虑限流,限流方法java 以令牌桶算法为主,而且Google也封装了方法为令牌桶方法,自己去开发很方便,但是要开发功能比较全面的方法,还是要一定的时间,所以就在github找了开源的方法,功能比较全,而且使用了设计模式,源码阅读性高,
大家有兴趣可以去研究一下。地址是github.com/ystcode/Sno… 一zwzt-server 服务引入限流
1.pom.xml 文件引入limit-starter
jar包
<dependency> <groupId>com.zwzt</groupId> <artifactId>zwzt-springboot-current-limit-starter</artifactId> <version>1.0.0.RELEASE</version> </dependency>
代码接入:
8521 是ticket-server ,到时候会上到测试环境,首先是注册到ticker-server 后台服务
2.限流方法实现注解方式,如果超过限流会降级
登陆server-ticket,可以查看多少服务实现了限流
使用ab测试:监控就是server-ticket 服务触发的
高考限流方案调研
背景:
为了应对高考2天期间的高流量,我们的活跃用户会有个急速的增长,在大量高并发的情况,经常会出现服务或接口面对暴涨的请求而不可用的情况,甚至引发连锁反应导致整个系统崩溃,为了保证我们的服务高可用,必须有一定的限流策略保证我们的系统不会崩溃。
现状:
目前我们的日活达到40w,作文纸条服务能很好的运行,在未来3个月近100天的时间,现在数据是注册用户1,200w,日活40w,日增注册用户4w,高考我们在日增不变的情况,
我们的日活应该达到40/1200 (1200+4*100)=55w,所以预计我们高考DAU在45w-55w之间,我们的兜底方案是保证45w核心用户能正常使用,而且通过这段时间验证,
目前我们的系统是经过DAU45w的考验,但是抗住100wDAU是我们今年的目标。
高考前我们优化接口按照 缓存-》降级-》限流 ,使用这3大抗高并发量的利器,预估我们的系统能抗住 50w-100w 的日活的并发量,当然这是在我们慢sql处理完成,bug处理好,升配的情况下。总结如下:
兜底方案,需要我们提前抽取一下活跃用户45w用户数据,保证这45w用户的高可用性。其他用户这2天就处于不可用状态。(nginx+lua) 期望目标方案:我们以优化接口,并在接口层做一个缓存+降级+限流的一个方式达到抗100wDAU,
兜底方案:
- 主要是在网关层: 网关层需要统一路口,现在我们的网关也是具备了这样的条件,只需稍微改造一下,就可以用。兜底方案就是一定要保证核心45w用户可用性,我们应该有个预备方案:
有2套隔离环境的服务,正常日常服务保证核心用户高可用,其他用户走新增的环境,这个环境只提供基本的查询业务,业务数据都在缓存中,或者直接给提示不可用。
2.优缺点分析: 优点:改动性不大,只需要抽取训练核心用户id,nginx +lua,如果另一套环境服务不能满足,另一套环境可以是灰度,或者直接不需要。
缺点:牺牲了部分用户的可用性。
期望目标方案: 这个方案主要现在我们优化一下我们的项目,然后抗住DAU100w,甚至DAU 1000w用户并发量
1.业务网关zuul: (1) 现在业务网关zuul是和服务耦合部署,是否把业务网关zuul 单独部署
(2)目前业务网关是zuul 1.0,它本质上就是一个同步Servlet,采用多线程阻塞模型,对高并发请求是一个瓶颈,是否可以改造成gateway 或者升级到zuul2
2.写库瓶颈 现在我们只有一个写库,一般mysql写库并发qps在2000-3000,在高考期间应该不会发生突发高并发的写操作,但是我们日常定时任务,push大量更新的时候还是要控制好写速率,考虑导致主从延迟,我们现在常见的bug。
3.服务端优化: 3.1 缓存优化: 很多并发瓶颈都在缓存上,如果缓存模块用的好,在我们现有基础上并发抗住1000wDAU 也是有可能的。
目前缓存只有用到了redis单机,这是一个限制我们系统的一个点,但由于考虑我们系统的用户量和增长量,推荐使用redis的主从部署,不需要使用redis的集群部署,优点是redis主从的话,抗住100w-1000wDAU是没问题的
,因为redis单机号称可以抗10wqp,除去网络及其他消耗,抗住6w-7w的qps 是没啥问题的,所以我们的系统,优化成redis一主2从就可以,因为用的是阿里的redis ,如果考虑高可用性,建立redis 哨兵模式(阿里的redis 高可用应该都达到5个9吧,所以没必要),
缺点主从模式对比集群模式可能会浪费redis的容量。
建立二级缓存,如MongoDB,由于一些复杂的业务,或者缓存特别大,可以考虑用二级缓存,这样能节省一点redis空间,MongoDB使用比较简单,可以作为二级缓存,也可作为,单机的本地缓存。
3.2 降级优化: (1)目前我们使用Hystrix接口超时降级用的比较好。
(2)请求限流没有使用,需要根据业务,核心接口需要保护起来,当请求量达到一定数量直接拒绝新来的请求
(3)熔断使用,像去年高考由于一些慢sql 超时问题,如果查询sql 配置 20次超时了5次 这个接口就熔断了,不去执行这个接口,执行sql,但是我们主体业务还是可以用的。
3.3 限流优化: 1.在网关层nginx 里限制同一个IP 1s请求同一个URL,只能请求2次,这样能防止恶意攻击,以及网络原因用户一直点击。
2.采用redis+lua令牌桶实现分布式服务限流,在核心服务加入限制请求次数是很有必要的。
3.在单个服务核心接口可以使用google的guava,令牌桶算法实现:平滑突发限流 ( SmoothBursty) 、平滑预热限流 ( SmoothWarmingUp) 实现。
4.关于上面实现方法网上有很多种,可见参考。
注册中心层面: 目前我们用的注册中心是eurka,但是由于eurka2.0 不再维护,现在我们45Wdau的时候,性能不会有所影响,但是健康检查一些其他的功能没有集成好,推荐改用阿里的nacos,
推荐理由:
1.这个开源项目已经2年了,有很多公司线上经验,是一个比较稳定社区活跃的开源项目了。
2.而且同时支持cp,和ap,也是集成了健康检查,配置中心,如果替换了就不用部署appllo项目,减少维护成本。
3.nacos 和Sentinel 也会有限流功能。
运维层面: 在运维层需要考虑每个服务的可用性监控报警,最好能监控cup 内存使用量,能动态添加新的服务节点。
关于核心用户抽取: 核心用户的抽取还是和产品确认,彪哥已经整理了一个用户模型,但感觉有点复杂,是否可以用现在活跃用户的id,这样更为简单。
以下是彪哥梳理抽取核心用户模型。
总结: 系统优化是个持续的过程,每一个优化都是一个专题,安排优先级,持续优化过程,当然这只是目前感觉比较紧急需要优化的点,后期如果写库是瓶颈的话,考虑将用户行为数据,点赞,评论数据不写库,迁移到es或者hbase中。
参考: