《分布式应用连接池负载不均问题分析.docx》由会员分享,可在线阅读,更多相关《分布式应用连接池负载不均问题分析.docx(20页珍藏版)》请在三一办公上搜索。
1、1、负我均衡基本概念1.1 负载均衡介绍在分布式架构下随着逻期业务的快速发展,系统架构也随之变得庞大且杂,这中间对系统模块的高并发、高可用、高扩展性也提出了新的要求,比如服务路由、负载均衡等.负载均衡是指将负载(如计克任务、数据流量等)分摊到多个操作单元(如服务器、网络设备等)上进行执行,以共同完成工作任务的一种技术.它建立在现有网络结构之上,提供了一种廉价、有效和透明的方法,可以扩展网络设备和服务器的带宽、增加吞吐最、加强网络数据处理能力,并提高网络的灵活性和可用性.负载均衡在实现上有硬件和软件两种方式:硬件负18均衡器功能强大、稳定性高.适合吞吐量大、高并发的流量负载,但是成本相对较高,并
2、且扩展性差;软件负觑部署上更加灵活,扩展性高,但是性能和稳定性相对较差.QQQQ11.11BareMetalVirtualizedContainersPublicCloud1)硬件负载均衡设备F5负载均衡器(1.TM):FSBIG-IP负载均衡设备,支持4-7层负载均衡,具备负载均衡、应用交换、状态监控等功能CDN负叠均衡设备:专门用于CDN的负载均衡设备,通常采用多层架构设计.包括全局负载均衡设备、局部负载均衡设备和缓存服务器等2)软件负载均衡1.VS:1.VS软件工作在网络四层,通过vrrp协议转发,有着高可用性、高性能、扩展性的优点,是1.inux内核的一款负载均衡软件。Nginx:Ng
3、inx软件工作在网络七层,它属于反向代理服务器,并且能够支持虚拟主机,是开源的负载均衡软件.HAProxy=HAProxy支持TCP和HTTP两种代理模式,它是一个反向代理服务器,支持虚拟主机,也可以用作HTTPS代理、基于内容的负载均衡等.1.2 负载均衡常用的算法负载均衡是将业务流盘负载到不同的服务器,而负载均衡算法就是实现在不同服务器之间分配网络流量的逻辑.负载均衡算法的选择会影响负载的分配机制,从而影响到性能和业务连续性,下面将介绍几种常用的负载均衡算法.1 )RoundRobin(轮询算法)轮询算法很简单,将前端请求按照顺序轮澹分配到后台服名器上,不用关心后台服务器的负载和实际连接情
4、况.轮询算法适用于后端服务器性能大致相当的情况.如果某台机器性能异常承载不了这么多的流量,会造成业务访问异常。当然在实际的运维工作中,会采用标准化的配置相同的服务器,以减少维护成本.如下图所示流量请求安装顺序分发到后台三个节点中,保证了流量均衡.2 )WeightedRoundRobin(加权轮询算法)加权轮询管法是对轮询算法的优化,因为后台服务器在配置和性能上有差异,在负载配置上将配宜高、负载低的机器分配更高的权束,使其能处理更多的请求,而配因低、负载高的机器,则给其分配较低的权至,降低其系统负载。加权轮询算法适用于后端具备不同负我容的服务器,但是配置上更为复杂,也不利于标准化的配舌.3 )
5、FastestResponseTime(最快响应凭法)最快响应算法根据负载均衡器到每一个后端服务器节点的网络响应时间(RTT时延),并将下一个到达的连接请求动态分配给响应时间最短的节点.该算法能培实现应用请求的快速响应,提高业务请求的响应时间,但是会出现请求集中在几个响应最快的节点上。如下图所示,节点1和节点3的响应时间为20ms、节点2为30ms,根据最快响应算法,连接请求负载分发到节点1和节点3中.4 )1.eastConnections(且小连接算法)像前面的轮询算法按照前端的请求次数均衡分配,实现后端服务器的负载均衡,但是实际上连接请求并不能真实反映服务器的负载情况.因此引入了最小连接
6、翼法,根据后端服务器当前的连接情况,动态的选取其中当前积压连接数展少的一台服务器来处理当前请求,尽可能的提高后台服务器利用率.最小连接算法在本质上是从后端服务器的角度来观察系疣的负载,能够最大限度的利用后端服务器的资源,不足之处是负载均衡需要更多的资源来判断后端服务的连接情况.如下图所示展小连接算法的实现:除了上面4种,负我均衡法还有随机法、加权的机法、源地址哈布法等不多介绍,实际应用中轮询算法和妙小连接算法应用的较多。2、DrUid连接池介绍2.1 Druid连接概盘Druid是开源的数据库连接池,它结合了C3P0,DBCP.Proxool等DB池的优点,同时加入了日志监控,可以很好的监控D
7、B池连接和SQ1.的执行情况.在druidDataSource中有一个电入锁和衍生的两个condition:一个监控连接池是否为空,一个监控连接池不为空.在druidDataSource中有两个线程,一个生成连接CreateConnectionThread,一个回收连接DestoryConnectionThread.在创建、获取、回收的时候都会使用这些锁和condition.每次获取Connection都会调用init,内部使用inited标识DataSource是否已经初始化0K.每次获取Connection都会需要进行加锁保证线程安全,所有操作都在加锁后执行.如果连接池内没有连接了,则调用
8、empty.signal(),通知CreateThread创建连接,并且等待指定的时间,被唤醒之后再去直看是否有可用连接.2.2 Druid参数配置说明1)基本属性name:配置这个属性的菽义在于,如果存在纺个数据源,监控的时候可以通过名字来区分开来。如果没有配置,将会生成一个名字,格式是:DataSoUrCe+System.identityHashCode(this).url:连接数据库的url,不同数据库不一样.例如:mysql:jdbc:mysql:/10.20.153.104:3306/druid2,oracle:jdbc:oracle:thin:10.20.149.85:1521:o
9、cnautoUSername:连接数据库的用户名password:连接数据库的密码driverClassName:这一项可配可不配,如果不配首druid会根据url自动识别dbType,然后选择相应的driverClassName2)连接池大小initialSize:初始化时建立物理连接的个数.初始化发生在显示调用init方法,或者第一次getConnection时.萩省值为0maxActive:最大连接池数量.缺省值为8minldle:最小连接池数最,缺省值为0maxWait:获取连接时最大等待时间,单位亳秒.配置了maWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配首U
10、seUnfair1.ock属性为true使用非公平锁.缺省值为-13)连接检测testOBorrow:申请连接时执行VaIidationQuery检测连接是否有效,做了这个配苗会降低性能.缺省值为truetestOnReturn:归还连接时执行ValidationQuery检测连接是否有效,做了这个配舌会降低性能.缺省值为falsetestWhileldle:建议配首为true,不影响性能,并且保证安全性.申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行ValidatiOnQUery检测连接是否有效。缺省值为falsetimeBetweenE
11、victionRunsMillis:有两个含义:1)DeStroy线程会检测连接的间隔时间,如果连接空闲时间大于等于minEvictableldleTimeMillis则关闭物理连接.2)testWhileldle的判断依据.缺省值为60smaEvictableIdleTimeMillis:连接空闲时间大于该值,不管minidie是多少都关闭这个连接.缺省值为7小时minEvictableldleTimeMillis:连接空闲时间大于该值并且池中空闲连接数大于minidie则关闭这个连接。缺省值为30分钟maxPoolPreparedStatementPerConnectionSize:要启用
12、PSCache,必须配普大于0,当大于0时,PooIPreparedStatements自动触发修改为true,在DrUid中,不会存在OraCIe下PSCaehe占用内存过多的问题,可以把这个数值配置大一些,比如说100.缺省值为-1PhyTimeoutMiIIis:物理连接打开的时间超过这个超时时间,并且不再使用时会关闭这个物理连接,一般不建议打开VaIidationQuery:用来检测连接是否有效的sql,要求是一个亘询语句,常用select,.如果VaIidatiOnQUery为null,testOnBorrow.testOnReturn、testWhileldle都不会起作用.缺省值
13、为nullVaIidationQueryTimeout:单位:秒,检测连接是否有效的超时时间.底层调用jdbcStatement对象的voidSetQueryTimeout(intseconds)方法.缺省值为-1keepAlive:连接池中的minldle数最以内的连接,并且连接的空闲时间大于keepAliveBetweenTimeMillis但小于miEvictableIdleTimeMillis,则会执行ValidatiOnQUery来保持连接的有效性.缺省值为falsekeepAliveBetweenTimeMillis:打开KeepAIive时,当连接的空闲时间超过该值,会使用Val
14、idationQuery执行一次直询,检直连接是否可用.缺省值为120s4)缓存语句PooIPreparedStatements:是否缓存preparedStatement,也就是PSCache.PSCache对支持游标的数据库性能提升巨大,比如说。racle.在mysql下建议关闭.缺省值为falseSharePrepareStatementsmaxPoolPreparedStatementPerConnectionSize:要启用PSCache,必须配舌大于0,当大于0时,PooIPreparedStatements自动触发修改为true.在DrUid中,不会存在OraCle下PSCach
15、e占用内存过多的问题,可以把这个数值配笈大一些,比如说100.萩省值为-12.3 连接保活和回收机制2.3.1 连接保活为了防止一个数据庵连接太久没有使用,而被其它下层的服务关闭,druid中定义了KeepAIive选项,机制上与TCP中的类似。保活机制能够保证连接池中的连接是百实有效的连接,线如遇到特殊情况导致连接不可用时,keepAlive机制将无效连接进行驱逐。保活机制是由守护线程DestroyConnectionThread发起的,启动后守护线程会进入无线循环,根据心跳间隔时间timeBetweenEvictionRunsMillis循环调用DestoryTask线程,默认时间为60s
16、.1)开启KeepAIive/一个连接在连接池中最小生存的时间dataSurce.SetMinEvictableIdleTiineMilliS(60*1。);单位矗秒开启keeAlivedataSource.SetKeePAIiVe(true);有两个参数KeePAIiVe和MinEvictabIeIdIeTimeMiIIis2)DruidDataSource中的两个成员变量/存放检杳需要撤ff的连接privateOruidConnectionHolderevictconnections;/用来存放需要连接检交的存活连接PriVateDruidConnectionHolderReepAlive
17、Connections;如果KeePAIiVe打开当一个连接的空闲时间超过keepAliveBetweenTimeMillis时,则会将此连接放入此连接放入keepAliveConnections数组,然后使用VaIidationQuery执行一次宜i询.if(keepAlive&IdleMillis三keepAliveBetweenTimeMillis)ReepAliveConnectionskeepAliveCount+connectionj-if(ReepAliveCount)/keeporderfor(inti=IceepAliveCount-1;i三;-i)DruidConnecti
18、onHolderholer=IceepAliveConnectionsi);Connectionconnection=holer.getConnection();holer.IncrementKeepAliveCheckCount();booleanvalidate-false;this.Validateconnection(Connection);validate-true;catch(Throwableerror)if(1.OG.IsDebugEnabledO)1.OG.debug(keepAliveErr,error);/skip如果本次ValidatiOnQUery执行失败,则关闭该链
19、接,并丢弃.2.3.2数据源收缩在DrUid数据源初始化的时候,会创建一个定时运行的DestroyTask,该任务的主要目的是将已空闲时间满足关闭条件的连接关闭.1)当前连接存活时长配JS的物理连接时间时长,则放入evictconnectionsif(PhyConnectTimeMillisphyTimeoutMillis)continue;evictconnectionsevictcount+=connection;2)空闲时间最小驱逐时间if(idleMillis=minEvictableIdleTimeMillis)if(CheckTime&iInaxEvictableIdleTimeM
20、illis)evictconnectionsevictcount+=connection;continue;.if(evictcount)for(inti-0;iminEvictableldleTimeMillis的连接,仅会关闭poolingCount-minldle个,后面的连接不受影响处于maEvictableIdleTimeMillis的空闲连接则会直接关闭timeBetweeEvictionRunsMillis即为该定时任务运行的间隔miEvictableIdleTimeMillis为可关闭连接的原小空闲时间2.4 Druid连接生命周期Druid连接的生命周期从两个维度去看:一个是
21、应用使用方,包括连接的申请、使用和关闭;一个是Druid自己管理的连接池,包括连接的创建和回收、保活机制等。具体如下所示:1)客户端连接管理客户端发起连接请求从Druid连接池申请连接,如果连接池内连接不够会调用CreateThread创建连接;客户端拿到连接后,访问数据而进行操作;连接操作完成后,释放数据库资源并dose连接,这一步通常是由应用主动去做的,连接关闭后会回收,归还给Druid连接池.2.5 DrUid连接池管理Druid连接池设置戢小连接数minldle和最大连接数maxActive,最小连接数支持预热功能,应用每次申请连接的时候不需要重新初始化,高并发下可以提升性能;连接池会
22、定时进行连接保活,KeePAliVe的周期由HmeBetweenEvictionRunsMiIiiS控制(默认值60s).当发现连接的空闱时长超过keepAliveBetweenTimeMillis(默认值120s)时,会主动发起链路保活,一般是向数据而发起SQ1.直询这个SQ1.语句可以自定义通常为selectIfromdual为了防止连接泄露,会定时回收空闲的连接,对于连接空闲时间大于minEvictableldleTimeMillis(默认为30分钟)并且连接池中空闲连接数大于minldle则关闭这个连接如果连接空闲时间大于maxEvictableldleTimeMillis(默认值为7
23、小时)则直接关闭连接从上可以看出,如果没有连接保活,当设置minldle后会有一部分在最小连接内的连接因为空闱连接超时被关闭;当然如果设百了KeepAIive并且当保活的检测频率和keepAliveBetweenTimeMillis小于FninEvictabIeIdIeTimeMilliS时,就不会出现空闲连接被关闭的情况.3、DrUid连接池下数据库负载不均问题3.1 负载均衡后端成员启动先后问还在日觉应用系统架构中,应用-负载均衡-数据库Si路如下图所示,应用测配目连接池以提升性能、负载均衡如F5设备实现后端成员的管理,如后端成员UP/DOWN状态监测、流量负载分发等.负载均衡通过定时检测
24、机制如TCP监听或者SQ1.语句探测,以监测后端成员的状态,记录到负载均衡设备中进行管理.在上图中部署了3个应用服务器,每个上面配置最小空闲连接minldle=2,总的初始化连接数有60个.当后端成员维护或者升级等原因集体处于DOWN状态然后再变成UP,但是对于负载均衡检测到后端成员的UP状态是有先后顺序的,比如DBl最先处于UP状态,后面其它DB陆续起来,这样大的连接最先到DBl节点,后面的DB节点也陆续有澹量.整个过程可能很快,12S的时间,但是反映在后端成员的流量负载上已经不均匀了(DBl=30、DB2=16,DB3=8、DB4=6).如果此时DBl节点的资源和性能不足以支撑50%的业务
25、流量,业务运行会变慢或者数据库请求失败,造成业务连续性影响.上述问题的一个优化方法是,如果是计划内的操作,在实施流程上迸行优化,在后端成员都就绪以后再将业务负载接入,这样会将流量请求相对均衡的负载到各个后端实例上.3.2 负黝均衡后端成员故阳后接入另一个场景是负载均衡后端成员故障后再重新接入的问跑,如上图所示,3个应用初始化连接为60,在负载均衡4个后端DB实例中平均为15.当后端成员DBl故障后其中的连接请求会均发到其它3个成员上,每个DB实例连接平均为20.但是当DBI实例重新接入负载均衡设备后,长时间没有连接请求接入,因为如果有新的连接请求过来,根据负载均衡兑法新接入的后端成员肯定会有负
26、载流量的.为什么会出现这样的问题,也是下面将介绍的连接池最小连接过大的问题.3.3 Druid连接池最小连接过大在前文Druid连接池生命周期管理中介绍到,Druid连接池设置最小连接数minldle支持颈热功能,应用每次申请连接的时候不需要全新初始化,高并发下可以提升性能.但是对于有些应用来说,初始化连接会设置过大,可能比业务蜂值的连接还大。比如A应用有20台应用服务器,每一台最小连接配置为20.这样总的最小连接支持400,但应用在业务峰值时候的Active连接不到350个,对应用来说性能是最佳的,因为不需要新建连接。但是这样就会出现负载均衡后端成员故障后再加入时候长时间没有连接的问题,因为
27、连接池中连接的销毁释放和新建是有个生命周期的.如何优化这个问题,让连接尽可能快速的销毁新建,并分发流量到新接入的成员中,一种是应用侧轮流启动以释放连接重新分发负毂流,这种机制对业务无感,但是不友好,每次涉及到后端成员的变更维护都要应用侧电启是不现实的.另一种是减少应用连接池的minldle配置,降低最小连接数,让前端及时的创建新的连接并负载到后端服务中,但这种对性能肯定有影峋.最终还是要从连接池的回收机制上出发,有两个参数minEvictableIdleTimeMillis(默认为30分钟)和maxEvictableIdleTimeMillis(默认值为7小时)rmaEvictableIdleTimeMillis表示如果连接空闲时间大于设定的值则会关闭连接.应用连接池使用情况/9斓%由6%f56FSfa%炉6产,%ActivcThreadmildteThred如上图所示应用连接池中最小连接和Active连接醺着每天业务变化情况,可以看到在凌晨业务低峰期Active连接并不高,当maEvictableIdleTimeMillis参数设置较小比如1小时,能够格连接池中的idle连接关闭睛毁井建立新的连接.这部分新建的连接又可以分发到负载均衡后端成员中,让新加入的节点能移接入流量.但这种连接的销毁建立对应用来说是有性能开销的,具体设亘多少合适,需要根据实际的性能压测结果进行评估。