软件开发的家园,编程爱好者的天地.

现在是:北京时间 2016/4/14 上午11:50:51 星期四

设为首页  |  加入收藏  |  网站地图

代码背后的点滴
发布于:第八基地 来源:互联网 作者:天堂路上 时间:2016-04-24 点击:294

有段时间没有更新技术blog了,现在有空每天都写写围脖,记录生活和工作的点滴,但是有时候发现有些技术的想法和工作总结没有像过去那么完整的写很大一篇,但是也有零零散散的不少点滴,因此想着随意的写这么一个连续的片段分享。   为什么叫做代码背后的点滴呢,其实在现在互联网应用来说,其实用什么语言,用什么平台有些场景有影响,但已经不是绝对重要的因素的,其实代码被后的设计思想才是最重要的。而用最熟悉的方式去表现最自然的想法,那才能做到游刃有余,就好比我向华黎同学申请这次内部奖励的奖品希望是手写笔,因为不论什么画图工具用起来都会妨碍我的顺畅的表达,最终我把注意力集中到了画本身上,而丢失了应有的灵感(在没有拿到画笔前,最近先少画点图)。写代码也是一样,不要被流行,高性能,有潜力这些词搞丢了自己的目标,工具就是工具,能广泛的去学,但不必要广泛的用,把干活要用的那门搞熟练了再说。废话不多说,言归正传。         

  先说一下,以下的任何观点都必须“对症下药”,没啥万能灵丹妙药,怎么用,什么时候用是关键。 

  聚与散    

  场景一,在分享时谈到Jetty7整个体系架构就一个线程资源池,为什么?整个jetty体系都是事件驱动模式(包括系统事件:NIO事件,包括业务事件:request suspend),我们系统很多时候有很多资源池(线程,DB,服务)等等,有些是直接的,有些是间接的(依赖于第三方包引入的)。我们要求每个开发者都要给资源池设置上限,给队列限定长度,防止崩溃,但是当这些资源池散落在各个地方的时候,那么每一个资源达到边界以前,总和可能已经超过了系统负载能力,那么一样会奔溃。因此资源的统一规划看来有必要,那可以考虑将物理隔离变成逻辑隔离(防止业务干扰,同时可以根据权重模型来动态分配和预留资源),另一方面整个小团队到大团队,对于连接池的使用抽象出来以后,那么多个依赖都可以在抽象的基础上公用一个物理资源池,如果引入第三方缓存,都可以将资源策略应用到多机上。回过来,这里就要说聚和散的关系,聚能够在一定程度上有全局观,同时可以根据策略模型来调配资源,散最大的好处就是业务隔离,互相不会影响。最近在写一个线程资源分配的小东西,目标就是:资源可根据权重模型分配。(权重模型两条:设定某一类key获取资源可以保留一定资源独享,设定某一类key获取资源最大上限可控)其实这就是一个逻辑隔离资源的最基本的雏形。        

   场景二,有同学谈起他们的系统属于消耗CPU类型的应用,特别是对数据库获取到的数据作处理和渲染的时候,问有啥好的建议。我的建议是数据获取端没啥可优化的话,考虑数据存入端增加数据预处理功能,将数据处理的压力分摊到更多也数据存入方。当然这个代价是数据的可复用性降低,业务逻辑侵入到其他系统,数据存入方性能会有所下降(如果这三点不足以影响业务流程和数据存入方,那么可做)。其实这是聚和散的另一种表现,很多时候需要考虑的是全局优化,而不是局部优化。      

   场景三,我今天看了淘宝Tair的作者若海介绍关于tair的一些设计思路的文章,这和早先我做memcached的客户端思想是有共同点的。首先就是数据的获取从服务端中转路由变成了客户端获得配置本地hash选择目标服务器,这就将服务路由的功能客户端化了,避免了单点的瓶颈,也提高了访问性能。同时metadata的数据保存在configserver中,以弱依赖的方式主动推送,避免客户端受到影响。但他的设计里面数据同步是服务端做的,而我当年是客户端做的(队列中异步备份),当时一方面是没有办法去改服务端的memcached,另一方面服务端能有多少,客户端有多少,这些压力的分摊,天然的缓解服务端的压力,将压力分散在了客户端上。(代价就是客户端工作多一点,即时性依赖于各个客户端的能力)这也是一种散。     

  场景四,TOP大数据请求的处理设计,TOP的目标是什么?大坝。主要职能:限流,授权,路由。那么路由这件事情必须在TOP走么,数据交互和平台校验是否一定要在一个流程中完成,其实不然,安全校验通过以后可以颁发会话标识和目标服务地址,直接由客户端和服务端交互。(这其实就和很多分布式文件系统或者分布式缓存系统一样的考虑,校验通过后就直接建立数据通道进行数据交互,避免性能受到影响),这了的聚和散就涉及到业务的耦合性分析决定流程的聚散,改善性能和稳定性。    

   场景五,上面谈到过最近自己实现资源分配逻辑隔离的这样的资源池,现在就是做线程池,起初不想用jdk自带的线程池,原因是自带线程池启动线程后,线程只要在coresize内就不会被销毁,也没有调度来从池里面获取执行任务,完成任务放回到资源池,这些线程就轮训的去获取队列的数据。好处在于没有一个manager的管理性能和复杂度会提升,缺点就是资源分配就无法实现。其实这就是典型的一种资源分配有一个实例主导还是由多个消费者自己主导的设计。

  强弱依赖         

  场景:Jetty的Continuation设计中,从调用suspend方法来悬挂起请求,避免退出容器service方法req和res被回收,到业务主动调用complete结束请求流程,回写数据到客户端,都采用产生事件,异步的由核心线程池去执行。这样业务线程池的线程生命周期就不会受到系统线程输出快慢或者容器本身压力的影响。这种弱依赖能够极大的解耦两个系统的服务能力和稳定性。 

  关键先生         

  场景一,有同学一个压力测试报告中做了这么一个测试,整个事务处理流程第一步骤消耗CPU,第二步骤消耗IO。整体事务时间=CPU 10 ms + IO 90 ms。他考虑是否能够通过缩短IO消耗时间或者CPU消耗时间来提升RT时间,就能够提升TPS。他的结果是IO提升一倍TPS没有任何变化,CPU消耗时间提升一倍,TPS翻番。这能说明啥,说明瓶颈在CPU上,提升一倍,那么处理能力增加一倍(就好比资源池内的资源生命周期缩短,被利用的次数更多),大部分请求都在CPU上排队等待处理,因此系统的TPS取决于瓶颈资源的处理能力而不是简单的缩短RT就可以改变的。(贴切的比喻就是漏斗,不论你大口朝上或者朝下,小口决定了水流量,小口就是那个关键先生)

下一篇:代码背后的点滴
对我有帮助
(0)
0%
对我没帮助
(0)
0%
返回顶部
在线反馈
在线反馈