当前位置: 首页 > 编程日记 > 正文

【性能优化之道】每秒上万并发下的Spring Cloud参数优化实战

一、写在前面

 

相信不少朋友都在自己公司使用Spring Cloud框架来构建微服务架构,毕竟现在这是非常火的一门技术。

如果只是用户量很少的传统IT系统,使用Spring Cloud可能还暴露不出什么问题。

如果是较多用户量,高峰每秒高达上万并发请求的互联网公司的系统,使用Spring Cloud技术就有一些问题需要注意了。

 

 

二、场景引入,问题初现

先不空聊原理、理论,来讲一个真实的例子,这是我的一个朋友在创业互联网公司发生过的真实案例。



朋友A的公司做互联网类的创业,组建了一个小型研发团队,上来就用了Spring Cloud技术栈来构建微服务架构的系统。

一段时间没日没夜的加班,好不容易核心业务系统给做出来了,平时正常QA测试没发现什么大毛病,感觉性能还不错,一切都很完美。

然后系统就这么上线了,一开始用户规模很小,注册用户量小几十万,日活几千用户。

每天都有新的数据进入数据库的表中,就这么日积月累的,没想到数据规模居然慢慢吞吞增长到了单表几百万。

这个时候呢,看起来也没太大的毛病,就是有用户反映,系统有些操作,会感觉卡顿几秒钟,会刷不出来页面。

这是为啥呢?

  • 核心原因是单表数据量大了一些,达到了几百万。

  • 有个别服务,跑的SQL比较复杂,一大堆的多表关联

  • 并且还没有设计好索引,或者是设计了索引,但无奈一些小弟写了上百行的大SQL,SQL实在太复杂了,那么一个SQL跑出来好几秒肯定是正常的。

如果大家对微服务框架有点了解的话,应该知道,比如Feign + Ribbon组成的服务调用框架,是有接口调用超时这一说的,有一些参数可以设置接口调用的超时时间。

如果你调用一个接口,好几秒刷不出来,人家就超时异常返回,用户就刷不出来页面了。

 

三、扬汤止沸,饮鸩止渴

一般碰到这种事情,一大坨屎一样的SQL摆在那儿,写SQL的人过一个月自己都看不懂了,80%的工程师看着都不愿意去花时间重写和优化。

一是修改的人力成本太高,二是谁敢负担这责任呢?

系统跑的好好的,就是慢了点而已,结果你硬是乱改一通,重构,把系统核心业务流程搞挂了怎么办?

所以,那些兄弟第一反应是:增加超时时间啊!接口慢点可以,但是别超时不响应啊!

咱们让接口执行个几秒把结果返回,用户不就可以刷出来页面了!不用重构系统了啊!轻松+愉快!

如何增加呢?很简单,看下面的参数就知道了:

 

大家如果看过之前的文章,应该知道,Spring Cloud里一般会用hystrix的线程池来执行接口调用的请求。

如果忘了这一点的,可以回头看看《拜托,面试请不要再问我Spring Cloud底层原理!》。

所以设置超时一般设置两个地方,feign和ribbon那块的超时,还有hystrix那块的超时。其中后者那块的超时一般必须大于前者。

Spring Cloud玩儿的好的兄弟,可千万别看着这些配置发笑,因为我确实见过不少Spring Cloud玩儿的没那么溜的哥们,真的就这么干了。

好了,日子在继续。。。

优化了参数后,看上去效果不错,用户虽然觉得有的页面慢是慢点,但是起码过几秒能刷出来。

这个时候,日活几千的用户量,压根儿没什么并发可言,高峰期每秒最多一二十并发请求罢了。

大家看看下面这张图,感受一下现场氛围:

四、问题爆发,洪水猛兽

随着时间的推移,公司业务高速发展……

那位兄弟的公司,在系统打磨成熟,几万用户试点都ok之后,老板立马拿到一轮几千万的融资。

公司上上下下意气风发啊!紧接着就是组建运营团队,地推团队,全国大范围的推广。

总之就是三个字推!推!推!

这一推不打紧!研发人员在后台系统发现,自己的用户量蹭蹭蹭的直线增长。

注册用户增长了几十倍,突破了千万级别,日活用户也翻了几十倍,在活动之类的高峰期,居然达到了上百万的日活用户量!

幸福的烦恼。。。

为什么这么说?因为用户量上来后,悲剧的事情就发生了。

高峰期每秒的并发请求居然达到了近万的程度,研发团队的兄弟们哪里敢怠慢!在这个过程中,先是紧张的各种扩容服务,一台变两台,两台变四台。

然后数据库主从架构挂上去,读写分离是必须的,否则单个数据库服务器哪能承载那么大的请求!多搞几个从库,扛一下大量的读请求,这样基本就扛住了。

正准备坐下来喝口茶、松口气,更加悲剧的事情就发生了。

在这个过程中,那些兄弟经常会发现高峰期,系统的某个功能页面,突然就整个hang死了,就是没法再响应任何请求!所有用户刷新这个页面全部都是无法响应!

这是为什么呢?原因很简单啊!一个服务A的实例里,专门调用服务B的那个线程池里的线程,总共可能就几十个。每个线程调用服务B都会卡住5秒钟。

那如果每秒钟过来几百个请求这个服务实例呢?一下子那个线程池里的线程就全部hang死了,没法再响应任何请求了。

大家来看看下面这张图,再直观的感受一下这个无助的过程!

 

这个时候咋办?兄弟们只能祭出程序员最古老的法宝,重启机器!

遇到页面刷不出来,只能重启机器,相当于短暂的初始化了一下机器内的资源。

然后接着运行一段时间,又卡死,再次重启!真是令人崩溃啊!用户们的体验是极差的,老板的心情是愤怒的!



画外音:

其实这个问题本身不大,但如果对Spring Cloud没有高并发场景的真实经验,确实可能会跟这帮兄弟一样,搞出些莫名其妙的问题。

比如这个公司,明明应该去优化服务接口性能,结果硬是调大了超时时间。结果导致并发量高了,对那个服务的调用直接hang死,系统的核心页面刷不出来,影响用户体验了,这怪谁呢?

 

五、追本溯源,治标治本

没法子了,那帮兄弟们只能找人求助。下面就是作者全程指导他们完成系统优化的过程。

第一步

关键点,优化图中核心服务B的性能。互联网公司,核心业务逻辑,面向C端用户高并发的请求,不要用上百行的大SQL,多表关联,那样单表几百万行数据量的话,会导致一下执行好几秒。

其实最佳的方式,就是对数据库就执行简单的单表查询和更新,然后复杂的业务逻辑全部放在java系统中来执行,比如一些关联,或者是计算之类的工作。

这一步干完了之后,那个核心服务B的响应速度就已经优化成几十毫秒了,是不是很开心?从几秒变成了几十毫秒!

第二步

 

那个超时的时间,也就是上面那段ribbon和hystrix的超时时间设置。

奉劝各位同学,不要因为系统接口的性能过差而懒惰,搞成几秒甚至几十秒的超时,一般超时定义在1秒以内,是比较通用以及合理的。

为什么这么说?

因为一个接口,理论的最佳响应速度应该在200ms以内,或者慢点的接口就几百毫秒。

如果一个接口响应时间达到1秒+,建议考虑用缓存、索引、NoSQL等各种你能想到的技术手段,优化一下性能。

否则你要是胡乱设置超时时间是几秒,甚至几十秒,万一下游服务偶然出了点问题响应时间长了点呢?那你这个线程池里的线程立马全部卡死!

这两步解决之后,其实系统表现就正常了,核心服务B响应速度很快,而且超时时间也在1秒以内,不会出现hystrix线程池频繁卡死的情况了。

第三步

事儿还没完,你要真觉得两步就搞定了,那还是经验不足。

如果你要是超时时间设置成了1秒,如果就是因为偶然发生的网络抖动,导致接口某次调用就是在1.5秒呢?这个是经常发生的,因为网络的问题,接口调用偶然超时。

所以此时配合着超时时间,一般都会设置一个合理的重试,如下所示:

设置这段重试之后,Spring Cloud中的Feign + Ribbon的组合,在进行服务调用的时候,如果发现某台机器超时请求失败,会自动重试这台机器,如果还是不行会换另外一台机器重试。

这样由于偶尔的网络请求造成的超时,不也可以通过自动重试避免了?

第四步

其实事儿还没完,如果把重试参数配置了,结果你居然就放手了,那还是没对人家负责任啊!

你的系统架构中,只要涉及到了重试,那么必须上接口的幂等性保障机制

否则的话,试想一下,你要是对一个接口重试了好几次,结果人家重复插入了多条数据,该怎么办呢?

其实幂等性保证本身并不复杂,根据业务来,常见的方案:

  • 可以在数据库里建一个唯一索引,插入数据的时候如果唯一索引冲突了就不会插入重复数据

  • 或者是通过redis里放一个唯一id值,然后每次要插入数据,都通过redis判断一下,那个值如果已经存在了,那么就不要插入重复数据了。

类似这样的方案还有一些。总之,保证一个接口被多次调用的时候,不能插入重复的数据。

六、总结全文,回眸再看

有图有真相!老规矩,最后给大家上一张图,最终优化后的系统表现大概是长下面这样子的。

如有收获,请帮忙转发,您的鼓励是作者最大的动力,谢谢!

作者:中华石杉,十余年BAT架构经验倾囊相授。个人微信公众号:石杉的架构笔记(ID:shishan100)

转载于:https://www.cnblogs.com/jay-wu/p/10149449.html

相关文章:

共话数据智能新经济,首届市北·GMIS 2019全球数据智能峰会隆重召开

7月19日,上海市市北高新技术服务业园区(以下简称“市北高新”)成功举办首届「市北GMIS 2019全球数据智能峰会」(以下简称“市北GMIS峰会”)。为期两天的市北GMIS峰会以“拥抱数智经济,赋能产业生态”为主题…

最新剑桥《AI全景报告》出炉:中国发表机器学习学术研究超过美国

来源 | 转载自新智元(ID:AI_era)2019年即将过去一半,剑桥大学的两位研究人员近日推出了本年度的State AI 2019全景报告。本报告基本沿袭去年的大体框架,从产业、人才、政策、预测等方面对过去一年来AI领域的技术的新进步、产业格局…

《OpenMP编译原理及实现技术》摘录

内容摘自《OpenMP编译原理及实现技术》第2章 代码测试环境:Windows7 64bit, VS2010, 4核机。 可以说OpenMP制导指令将C语言扩展为一个并行语言,但OpenMP本身不是一种独立的并行语言,而是为多处理器上编写并行程序而设计的、指导共享内存、多…

C# 36进制转10进制

代码是Java转过来的,变量名都没有改……有空再整理一下好了。public long toDecimal(string input, long bs){try{long Bigtemp 0, temp 1;int len input.Length;for (int i len - 1; i > 0; i--){if (i ! len - 1)temp * bs;long num changeDec(input[i]);…

Oracle Cloud Native Framework推出云原生解决方案

摘要:Oracle Cloud Native Framework云原生平台提供托管云服务和本地软件,同时在现Oracle云基础架构上跨应用程序配置和分析大量服务。developer relations for Oracle Cloud Infrastructure副总裁Bob Quillin讨论了该框架的优势以及对2019年云原生市场的…

OpenMP知识点汇总

1. OpenMP(Open Multi-Processing)官网:http://openmp.org/wp/ 2. OpenMP最新版本4.0,2013年7月发布。Visual Studio 2010内置支持OpenMP2.0,选中工程属性->C/C->Language->Open MP Support:选中Yes(/openmp)即可,然后在…

chsop 兼容jquery(解决与transport.js冲突)

2019独角兽企业重金招聘Python工程师标准>>> $(function() { window.__Object_toJSONString Object.prototype.toJSONString; delete Object.prototype.toJSONString; }); 要用到jquery的页面放入此代码即可 转载于:https://my.oschina.net/netmouse/blog/1241…

进程详细剖析(二)

摘自《C多核高级编程》 5.6.3 进程状态 在进程执行期间,它的状态会发生改变。进程的状态时指进程的当前状况。在POSIX兼容的环境中,进程可以处于以下状态: 1)运行(running) 2)就绪(runnable, r…

AI算力需求6年增长30万倍,「超异构计算」才能满足下一个10年

今年 3 月,「强化学习教父」Richard Sutton 在《苦涩的教训》一文中指出,「70 年的人工智能研究史告诉我们,利用计算能力的一般方法最终是最有效的方法。要在短期内有所提升,研究人员要利用专门领域的人类知识。但如果想要长期的获…

一览六月最热的5篇AI技术论文

作者 | 神经小姐姐转载自HyperAI超神经(ID: HyperAI)导语:始建于 1991 年的 arXiv.org 至今已收录超过 100 万篇论文预印本,近年来,其每月提交量已经超过 1 万篇。这里成为一个巨大的学习宝库。本文罗列了 arXiv.org 上…

OnCheckedChanged的触发需要AutoPostBack=true

OnCheckedChanged的触发需要AutoPostBack"true"

OpenCV中resize函数五种插值算法的实现过程

最新版OpenCV2.4.7中,cv::resize函数有五种插值算法:最近邻、双线性、双三次、基于像素区域关系、兰索斯插值。下面用for循环代替cv::resize函数来说明其详细的插值实现过程,其中部分代码摘自于cv::resize函数中的源代码。 每种插值算法的前…

企业金融云存储建设之路

当前世界形势千变万化,各种技术创新层出不穷,新兴业务模式也是波谲云诡,企业的信息化建设如何紧跟业务,适应业务乃至驱动业务转型是各级管理者的头等题目。对于底层执行者,如何能够快速满足企业的要求,如何…

【原创】VB利用堆栈实现算术表达式计算

这个抽象算法早已为人所知,只不过在VB的公开文档中鲜见示例代码。于是,为了提高自己的程序设计水平,锻炼自己的能力,我写了如下代码。 【VB代码版权所有,允许转载修改用作学习目的,转载必须注明来源】 【求…

树莓派4与英伟达Jetson Nano性能大比拼,谁是最佳的嵌入式“电脑”?

作者 | Chris Pietschmann译者 | 弯月,责编 | 屠敏转载自CSDN(ID:CSDNnews)导读:日前,Raspberry 基金会发布了开发者为之兴奋的 Raspberry Pi 4,其不仅在性能上进行了全面的升级,而且…

作为互联网流量入口,CDN日志大数据你该怎么玩?

CDN是非常重要的互联网基础设施,用户可以通过CDN,快速的访问网络中各种图片,视频等资源。在访问过程中,CDN会产生大量的日志数据,而随着如今越来越复杂的网络环境变化,和业务的迅速增长,日志数据…

OpenCV中图像旋转(warpAffine)算法的实现过程

在OpenCV中,目前并没有现成的函数直接用来实现图像旋转,它是用仿射变换函数cv::warpAffine来实现的,此函数目前支持4种插值算法,最近邻、双线性、双三次、兰索斯插值,如果传进去的参数为基于像素区域关系插值算法(INTE…

10亿美元续命!OpenAI获微软投资,意在通用人工智能?

来源 | OpenAI官博译者 | 孙薇编辑 | 一一出品 | AI科技大本营(ID:rgznai100) 7 月 22 日,微软宣布将对非营利人工智能研究组织 OpenAI 投资 10 亿美元,用于通用人工智能(AGI)的开发。双方将以微软原有的公…

TrayIcon 类 添加系统托盘不显示托盘图标

为什么80%的码农都做不了架构师?>>> 好久不碰 java swing最近写了一个swing 程序 添加托盘时,怎么也不显示图标,就一空白 ,在网上搜了老半天,大部无效。 边看帖子边看 java api ,结合理解,有一属性设置了一…

Crystal Report 加载模板报错 无法在c++ 堆栈中打开由jrc 引擎处理的文档

2019独角兽企业重金招聘Python工程师标准>>> 纠结了很久, 尝试过录入一个错误的路径,文件读取也是包相同的错误,也就是表示找不到路径文件而已,并不是开发环境的问题 于是设置一个最简单的路径,放置下去rpt模板,代码后续没有报错; 再次之前也修复了一个关于引用的dl…

Ubuntu下makefile及gcc生成静态库动态库的简单使用举例

环境:Ubuntu-13.10 32位(虚拟机)、gcc4.8.1 首先创建一个test_makefile_gcc文件夹,此test_makefile_gcc文件夹下包括:src文件夹用于存放源文件; include文件夹用于存放头文件;bin文件夹用于存放生成的动态库.so文件&…

Exchange Server 2013 安装完成后配置外部URL

Exchange Server 2013 安装完成后配置外部URL 比如 mail.contoso.com 1、转到 EAC → “服务器”,然后单击“配置外部访问域”。2、在“选择要与外部 URL 一起使用的客户端访问服务器”下面,单击“添加”3、选择您要配置的客户端访问服务器,…

Ubuntu下CodeBlocks的安装、配置及静态库动态库的简单使用举例

1、 从Ubuntu Software Center中搜索Code::Blocks并安装; 2、 在第一次启动时选择GNU GCC Compiler作为默认的编译器; 3、 生成静态库并调用操作步骤,代码同 http://blog.csdn.net/fengbingchun/article/details/17994489 3.1、New fil…

React 打怪笔记

介绍 本文为学习react中的记录。 Tips: 当组件的props或state有变化,执行render函数。无论是使用函数或是类来声明一个组件,它决不能修改它自己的propsReact 可以将多个setState() 调用合并成一个调用来提高性能。无状态函数式组件 (stateless functiona…

新闻智能分类练习赛开始报名啦!最先达到80分就可以领GPU,技术书籍!

现代信息爆炸般地产生,信息如海如潮。信息分类,不仅有利于加快信息检索速度,且有利于提高查准率。Internet是信息的重要载体,深入地研究与探讨网上信息自动分类的方法、技术和理论,已成为时代的迫切需求和新的研究热点…

项目经理应该具备的技能

作为一个优秀的项目经理应该具备五个方面的技能: 项目管理知识体系 应用领域的相关知识、标准和规则项目环境知识一般管理知识软技能/人际关系技能项目管理知识体系 就是要掌握常说的9大知识领域:范围、时间、成本、质量、人力资源、风险、沟通、采购再加上集成…

SSE2 Intrinsics各函数介绍

SIMD相关头文件包括&#xff1a; //#include <ivec.h>//MMX//#include <fvec.h>//SSE(also include ivec.h)//#include <dvec.h>//SSE2(also include fvec.h)#include <mmintrin.h> //MMX#include <xmmintrin.h> //SSE(include mmintrin.h)#incl…

中国城市道路名图鉴

作者| AlfredWu来源 | Alfred数据室&#xff08;ID&#xff1a;Alfred_Lab&#xff09;不知道大家出差或旅游的时候有没有发现&#xff0c;有些城市特别喜欢使用其它城市或者省份的名字作为道路名&#xff0c;特别是青岛市&#xff0c;这会儿还在徐州路&#xff0c;走过一个街区…

中国电子信息产业发展研究院主办的2018中国软件大会上大快搜索“又双叒叕”获奖了...

大快搜索自荣获“2018中国大数据企业50强”殊荣&#xff0c;12月20日在由工信部指导&#xff0c;中国电子信息产业化发展研究院主办的2018中国软件大会上&#xff0c;大快搜索获评“2018中国大数据基础软件领域领军企业”称号&#xff0c;入选中国数字化转型TOP100服务商&#…

SystemCenter2012SP1实践(15)共享库服务器和ISO

用过HyperV的同学都知道&#xff0c;HyperV调用ISO作为启动光盘的时候&#xff0c;必须保存在本地才行。网络共享下的一概不认。在SCVMM下&#xff0c;我们可以通过一些设置&#xff0c;让SCVMM下创建的虚拟机&#xff0c;支持调用不在同一台主机上的ISO文件。我是分隔线首先要…