架构师之路--限流技术和泛谈各类编程语言

  高并发服务必须有一些紧急方案,比如服务熔断,降级,隔离,限流,异步RPC等。服务熔断,降级,隔离大家比较倾向于用netflix开源的分布式服务弹性框架Hystrix。Hystrix也可以限流。但是我们服务用的guava的RateLimiter这种成熟的令牌桶算法来实现。

  服务限流是个很简单的事情。我们的代码也就几百行,但是里面有一套比较完整的设计思想,目的是根据一定的策略(如:url, 平台来源,url+平台来源)来做一个业务细粒度的限流。

  

  所有的请求都要走这个拦截器,这个拦截器里定义了一个单例的限流持有者,这个限流持有者按照配置的策略和配置的每个或者每种请求的限额来构成的map来返回给拦截器请求对应的key和RateLimiter。拦截器里判断超限则直接返回错误不交给控制器处理。一个请求类型,如url一个RateLimiter细粒度限流。

  当然,除了这种应用级别的限流,在nginx层面也可以做一些对IP的session空间,请求频率,并发量的限制。如果遇到网络攻击,尽量先从运维层面去解决问题,因为越往上层,对服务的影响能降到最低。

  一个好的软件架构能够满足系统的品质,使受益人达成一致的目标,能够支持计划编制过程,对系统开发的指导性,能够有效的管理复杂性,为复用奠定了基础,能够降低维护费用,能够支持冲突分析。但是做到这些之前,先要从一些最基本的做起。比如我24岁就结婚了,不然怎么面向对象编程。然后刚结婚就生娃了,不然对象跑了咋办?new一个?创建销毁开销很大的,还是生个娃持续持有对象的引用的好。

  绝大多数架构或者编程语言的产生都是来源于项目。比如C++的发明者Stroustrup设计这个语言的初衷是看到C语言由于不合理的初始化参数导致至关重要的编程问题,这种bug很难发现。这种问题在清理的时候同样出现。做了坚持了,确实就成功了。然而任何一个东西都有一个形成和发展的阶段。java在老一些的版本中一直被吐槽性能问题,而它的每一个版本都要伴随着性能的提升,所以升级JVM就能带来免费的性能福利。细节处想到final关键字,在早期的版本中,final关键字的部分会内联调用,直接将函数展开,而不用不断的参数入栈出栈而引起性能开销。但是这个在函数体大的时候会有空间上比较大的开销。JVM在1.5开始进行了优化,final关键字性能上的作用就不再那么大了。原来公司有个同事,人很好,也很有想法。他说:“我总是会将自己的一些想法记录在一个本子上,然后过一段时间再看就会发现,我那篇只坚持了当时的其中一个想法,去做了,都成功了。”我认为他离成功比自己想象的要远很多。因为他有的只是想法,并没有去做。就好像只有JDK1.0的想法,但是路程离成功至少有离jdk1.5的距离。

  Python以代码量小,维护成本低,编程效率高著称。但是哪有几个编程语言不是以维护成本低,编程效率高作为优化点的呢?所以人家问我搜索引擎已是一片火海,你将来真的能打造出自己的优势吗?我只能说不试怎么知道。“人生苦短,我用python”。Python的这些特点可以腾出更多的时间去把妹了,可不就人生苦短了嘛。Python作者的广告词给了Python生命力。实际上Python的简单性从它的内存回收就可见一斑,它用的是引用计数法,可见不存在循环引用问题。我在人人的时候做过一个python的项目。有段时间我们领导说我一个人做了8个人的活儿。除了整个网站所有的维护工作之外,各种新活儿我都接。就是这个性格,别人实在没办法来找我了,我只为难自己,不为难别人。那时候工作不到四年,编程时间不到两年,我说过工作头两年是当日语翻译的。之所以能去人人。话说一日我刚来北京,和学长正在逛颐和园,突然接到人人网面试电话,电话那头问我各种技术问题,我的回答都是不会。结果那头非常nice的说没关系。最后电话那头换了一个面试官,用日语给我讲话,问我做了啥,她对我的回答非常满意,满意主要是发现我日语非常好。结果我就成了人人网的桥梁工程师。记得我前面写的文章里个人简介里写凭借自己的语言天赋被网友吐槽了,但是我在东软的时候人人都说我有语言天赋,我自己也就习惯这么认为了,我只是理所当然的认为自己在陈述一件事情,并没有标榜的意思。我也不会python,我也根本不知道啥是开放平台。但是我一个人接手负责整个开放平台的维护,因为开放平台的老大跳槽去美团了。话说这个老大真是个牛人,清华的,创过业,来了人人,又去美团做到了P4,现在又自己创业去了。有一天我家男神拿着一个清华校友会的照片问我:“这个人好像是你原来同事吧”。我说:“嗯呢”。他说:“他旁边坐的是我们老板”。好吧,看来我家男神可进步的空间不是一般的大。

  我硬着头皮维护这个开放平台。然后泡泡鱼游戏要接入一个日本平台。这个游戏是python写的。那时候这款游戏非常火,这个游戏公司超级忙,没时间给接入,给钱找我们帮忙。我们只能自己把代码拿过来接入。那时候人人网喜欢搞内部创业,我们是海外事业部,本来就是不赚钱的。我做了那个接入,游戏方给了我们10万接入费,剩下的就是游戏分成,收入我就不知道有多少了。但是这是我们那时候唯一赚钱的一个项目了。Python真是非常好学,我白天维护网站,所有的人都来找我,晚上做接入,研究python和接入文档,1周时间把支付接入部分搞定了。测试环境可以充钱了。但是上线有问题,运维MM搭建的正式环境跑的时候有一块怎么都不对。晚上所有人都回家了,我自己在那里弄线上环境。后来终于发现安装的一个部分一个工具的版本不对,具体怎样不记得了。6年前的事情了。所以我做过python,但是不会python。

  Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进入,墙里面的人却想出来。Java上不能那么随意,也就是优化一下内存分配参数,说起JVM参数优化,其实最常用觉得人人都知道不当回事的就是堆的初始最大值和最小值设置成相同的值,这样避免堆自动扩展,调整新生代和年老戴的大小的full gc造成的吞吐量降低和延迟。话说JVM的几乎所有gc操作,包括minor gc都要stop the world.

  为啥有些人开口说话能说很久,有些人说话有一搭没一搭的?据我观察发现,动手干活差不多的两个人,会说的将来发展的会更好。原因从具体实例来感受一下。

  和朋友聊天,真的,好几年前人人网出来的总有点技术极客精神,聊天我们聊技术。人家问我你们视频是怎么存储怎么播放的。我说我就是做内容,meta的,其他和我无关。天儿就聊死了,自己的格局就下来了。如果说我做的有开发平台的东西,里面有上传视频的。先调用云存储的接口进行一个初始化,他们返回给我们一个视频介质上传url。JS端将介质分片的方式上传到url上。如果网络中断或者浏览器关闭啥的,可以调用续传接口用新返回的url继续传。续传接口带着总文件大小和目前已经收到的文件的大小,JS可以依据这个判断从哪个分片继续传。云存储在另一个部门,他们负责和云转码部门进行通信,云转码将介质转成各种格式,至于从原始高清文件转成各种码率,怎样取样的,由云转码部门负责。他们内部是用什么策略分发到各个DNS节点上的。调度部门又是怎样调度来节约视频网站最宝贵的带宽的,具体细节我不是很清楚。云转码部门将转换好的各种码率和视频url通过MQ的形式传给我们,我们存到数据库里。

  那人家就又问了,MQ你们用的啥呀?我说apache的qpidd。额~~,人家不知道,聊天就聊死了。所以得说MQ都差不多的,和rabbit mq一样都是基于AMQP高级消息队列协议的。这是公司统一的集群,说是安装部署挺方便的。主流的编程语言也都支持,所以就用了。因为主要是跨部门的通信,主要以方便,节约沟通成本为主,所以我们的消息体也就是json先压缩再base64。也没用protobuf那些二进制的,因为万一遇到问题,二进制可读性差,缺乏自描述,不容易排查。

  最后给大家推荐一个国外的网站http://blog.takipi.com/。经常会介绍一些实用工具和调优技巧,注重分析。代表作有http://blog.takipi.com/7-new-tools-java-developers-should-know/和http://blog.takipi.com/how-to-instantly-improve-your-java-logging-with-7-logback-tweaks/

posted @ 2017-06-18 18:49 静儿1986 阅读(...) 评论(...) 编辑 收藏