Dubbo之父——梁飞技术博客拾遗(4)
服务架构演进
2011-12-28 https://www.iteye.com/blog/javatar-1329022
Dubbo用户指南中缺少背景,简单想了一下服务架构演进过程:
单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。
此时,用于简化增删改查工作量的 数据访问框架(ORM) 是关键。
垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。
此时,用于加速前端页面开发的 Web框架(MVC) 是关键。
分布式服务架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。
此时,用于提高业务复用及整合的 分布式服务框架(RPC) 是关键。
流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心,基于访问压力实时管理集群容量,提高集群利用率。
此时,用于提高机器利用率的 资源调度和治理中心(SOA) 是关键。
服务治理过程演进
2012-01-13 https://www.iteye.com/blog/javatar-1345073
在大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡。
- 当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。
此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。
并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。
- 当进一步发展,服务间依赖关系变得错综复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。
这时,需要自动画出应用间的依赖关系图,以帮助架构师理清理关系。
- 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?
为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。
其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阀值,记录此时的访问量,再以此访问量乘以机器数反推总容量。
- 规模继续扩大,应用之间不再是扁平的对应关系,开始分层,比如核心数据层,业务集成层等,就算没有出现循环依赖,也不允许从低层向高层依赖,以免后续被逼循环依赖。
这时,需要在注册中心定义架构体系,列明有哪些层的定义,每个服务暴露或引用时,都必须声明自己应用属于哪一层,这样注册中心能更快的发现架构的腐化现象。
- 服务多了,沟通成本也开始上升,调某个服务失败该找谁?服务的参数都有什么约定?
这时就需要登记每个服务都是谁负责的,并建立一个服务的文档库,方便检索。
- 慢慢一些敏感数据也都服务化了,安全问题开始变得重要,谁能调该服务?如何授权?
这样的服务可能需要一个密码,访问时需带着此密码,但如果用密码,要改密码时,就会很不方便,所有的消费方都要改,所以动态生成令牌(Token)可能会更好,提供方将令牌告之注册中心,由注册中心决定是否告之消费方,这样就能在注册中心页面上做复杂的授权模型。
- 就算是不敏感的服务,也不是能任意调用,比如某服务突然多了一个消费者,这个消费者的请求量直接把服务给拖跨了,其它消费者跟着一起故障。
首先服务提供方需要流控,当流程超标时,能拒绝部分请求,进行自我保护。
其次,消费者上线前和提供者约定《服务质量等级协定(SLA)》,SLA包括消费者承诺每天调用量,请求数据量,提供方承诺响应时间,出错率等,将SLA记录在监控中心,定时与监控数据对比,超标则报警。
- 虽然有SLA约定,如果不能控制,就只是君子协定,如何确保服务质量?
比如:一个应用很重要,一个不那么重要,它们调用同一个服务,这个服务就应该向重要应用倾斜,而不是一视同仁,当支撑不住时,应限制不重要应用的访问,保障重要应用的可用,如何做到这一点呢。这时,就需要服务路由,控制不同应用访问不同机器,比如:
应用分离:
1
2
consumer.application = foo => provider.host = 1,2,3
consumer.application != foo => provider.host = 5,6
读写分离:
1
2
method.name = find*,get* => provider.host = 1,2,3
method.name != find*,get* => provider.host = 5,6
- 服务上线后,需要验证服务是否可用,但因防火墙的限制,线下是不能访问线上服务的,不得不先写好一个测试Main,然后放到线上去执行,非常麻烦,并且容易忘记验证。
所以线上需要有一个自动运行的验证程序,用户只需在界面上填上要验证的服务方法,以及参数值和期望的返回值,当有一个服务提供者上线时,将自动运行该用例,并将运行结果发邮件通知负责人。
- 服务应用和Web应用是有区别的,它是一个后台Daemon程序,不需要Tomcat之类的Web容器。但因公司之前以Web应用为主,规范都是按Web应用的,所以不得不把服务跑在一个根本用不上的Web容器里,而搭一个这样的Web工程也非常费事。
所以需要实现一个非Web的容器,只需简单的Main加载Spring配置即可,并提供Maven模板工程,只需mvn dubbo:generate 即可创建一个五脏俱全的服务应用。
- 开发服务的人越来越多,更注重开发效率,IDE的集成支持必不可少。
通过插件,可以在Eclipse中直接运行服务,提供方可以直接填入测试数据测试服务,消费方可以直接Mock服务不依赖提供方开发。
- 因为暴露服务很简单,服务的上线越来越随意,有时候负责服务化的架构师都不知道有人上线了某个服务,使得线上服务鱼龙混杂,甚至出现重复的服务,而服务下线比上线还困难。
需要一个新服务上线审批流程,必须经过服务化的架构师审批过了,才可以上线。
而服务下线时,应先标识为过时,然后通知调用方尽快修改调用,直到没有人调此服务,才能下线。
- 因服务接口设计的经验一直在慢慢的积累过程中,很多接口并不能一促而蹴,在修改的过程中,如何保证兼容性,怎么判断是否兼容?另外,更深层次的,业务行为兼容吗?
可以根据使用的协议类型,分析接口及领域模型的变更是否兼容,比如:对比加减字段,方法签名等。
而业务上,可能需要基于自动回归测试用例,形成Technology Compatibility Kit (TCK),确保兼容升级。
- 随着服务的不停升级,总有些意想不到的事发生,比如cache写错了导致内存溢出,故障不可避免,每次核心服务一挂,影响一大片,人心慌慌,如何控制故障的影响面?服务是否可以功能降级?或者资源劣化?
应用间声明依赖强度,哪些功能强依赖,哪些弱依赖,然后基于依赖强度,计算出影响面,并定期测试复查,加强关键路径上的服务的优化和容错,清理不该在关键路径上的服务。
提供容错Mock数据,Mock数据也应可以在注册中心在运行时动态下发,当某服务不可用时,用Mock数据代替,可以减少故障的发生,比如某验权服务,当验权服务全部挂掉后,直接返回false表示没有权限,并打印Error日志报警。
另外,前端的页面也应采用Portal进行降级,当该Portal获取不到数据时,直接隐藏,或替换为其它模块展示,并提供功能开关,可人工干预是否展示,或限制多少流量可以展示。
- 当已有很多小服务,可能就需要组合多个小服务的大服务,为此,不得不增加一个中间层,暴露一个新服务,里面分别调其它小服务,这样的新服务业务逻辑少,却带来很多开发工作量。
此时,需要一个服务编排引擎,内置简单的流程引擎,只需用XML或DSL声明如何聚合服务,注册中心可以直接下发给消费者执行聚合逻辑,或者部署通用的编排服务器,所有请求有编排服务器转发。
- 并不是所有服务的访问量都大,很多的服务都只有一丁点访问量,却需要部署两台提供服务的机器,进行HA互备,如何减少浪费的机器。
此时可能需要让服务容器支持在一台机器上部署多个应用,可以用多JVM隔离,也可以用ClassLoader隔离。
- 多个应用如果不是一个团队开发的,部署在一台机器上,很有可以误操作,停掉了别人的服务。
所以需要实现自动部署,所有的部署都无需人工干扰,最好是一键式部署。
- 机器总是的闲时和忙时,或者冗余机器防灾,如何提高机器的利用率?
即然已经可以自动部署了,那根据监控数据,就可以实现资源调度,根据应用的压力情况,自动添加机器并部署。
如果你的应用是国际化的,有中文站,美国站之类,因为时差,美国站的机器晚上闲的时候,可能正是中文站的白天忙时,可以通过资源调度,分时段自动调配和部署双方应用。
按关键词归纳为:
- 服务注册与发现
- 软负载均衡与容错
- 服务监控与统计
- 服务容量评估
- 服务上线审批
- 服务下线通知
- 服务负责人
- 服务文档
- 服务路由
- 服务编排
- 服务黑白名单
- 服务权限控制
- 服务依赖关系
- 服务分层架构
- 服务调用链跟踪
- 故障传导分析
- 服务降级
- 服务等级协定
- 服务自动测试
- 服务伪装容错
- 服务兼容性检测
- 服务使用情况报告
- 服务权重动态调整
- 服务负载均衡调整
- 服务映射
- 服务模板工程
- 服务开发IDE
- 服务健康检测
- 服务容器
- 服务自动部署
- 服务资源调度
能力成长模型
2012-05-09 https://www.iteye.com/blog/javatar-1517933
最近看了温伯格1986年出版的《技术领导之路》,
很老的书,讲的都是一些浅显但容易被忽视的道理,
就像第一章,讲作者自己玩弹子球的水平提升,
时间长了,以为自己的水平提升像下图这样,每年都在逐步提升:
而实际上往往不是,能力的提升过程通常都是“高原-突破”式的,
在高原时期沉淀和思考,在学会新方法后突破,
不善于思考和总结的人,高原期就会特别长,而且人在高原期总会觉得很安逸:
并且在突破前一般还会有低谷期,就像下图的“高原-低谷-突破”模型,
要想突破,就必须努力打破安逸的现状,实践新想法、新知识、新方法,
在新的方法没有成熟之前,你会觉得还不如以前好,这就是低谷期,
总想退回老办法上去,尤其是在和别人对比的时候,一定要Hold住:
当然,实际数据不会像上面模型那样平滑,下图是作者玩弹子球水平的数据,
因为作者从小就买了一台弹子球机,上面记录了他所有的成绩:
如何解决问题
2012-08-02 https://www.iteye.com/blog/javatar-1617775
最近打算去新的岗位,尝试新的业务,当然也就需要新的思考,新的碰撞,想起前段时间看过温伯格1982年出版的《你的灯亮着吗?》,把序言中的总结点摘录下来,希望能给自己带来些许思路。
问题其实就是你期望的东西和你体验的东西之间的差别。
- 动手去解决问题之前,好好想想问题的来源;
- 如何站在各个角度来看待面临的问题,以能够知道其真正所在;如何去尝试那个最能解决真正问题的方法,并且时刻保持警惕心;
- 为什么不要把人们的解决方法误认为是问题的定义,更不要把某个问题的解决方法误认为是问题的定义,特别是这个解决方法是你自己所使用的;
- 永远都不要肯定自己已经有了一个正确的定义,即使是在问题好像已经解决之后。
- 每一种解决方法都会带来新的问题;
- 问题最难以处理的部分恰恰是去意识到它们的存在;
- 在理解问题之前,至少要做好准备接受三种可能的出错情况;
- 或许还可以改变问题的表述来获得不同的解决方法;
- 当你沉迷于寻找问题定义和解决方法时,不要忘记随时都回头看看,看看自己是不是已经迷路了……
- 当别人能够很好地解决自己问题的时候,千万不要越俎代庖;
- 如果某人能够解决这个问题,但是他本人却并不会遇到这一问题时,那么你首先要做的就是让他也感受到这一问题;
- 不管看上去如何,人们很少知道他们要什么,直到你给了他们所需要的东西;
- 甚至,事实上,并没有多少人真的希望他们的问题被解决。
真正的问题所在可能并不是您现在的所想,换个角度分析,或许您已经找到了问题的真谛。
奇异的恩典
2014-10-01 https://www.iteye.com/blog/javatar-2124323
看了部老电影《奇异的恩典》,讲英国废奴法案的事,威伯福斯一心推动废奴法案,因议会贵族在这上面都有利益在,推了多年也没有进展,英法战争开始后,大家的焦点都在战争上,其它议案没人理会,虽大声疾呼也没啥见效,支持的团队都要散伙了。
前面这些只是背景,关键觉得他们的突破策略很有意思,即然大家都在关心战争,因法国船支为避免战争均挂美国等中立旗,那就提“打击所有挂中立旗船支”的法案,可有效打击法国船支的通航,为战争取得主动权,由一个不起眼的议员提案,很容易就通过了。同样,黑奴的船支也是挂中立旗的,这一打击,黑奴的船也没法运了,过了两年,等倒卖黑奴变少了,再去煽动废奴法案,因议会贵族在黑奴上的利益已经没那么大,再加上舆论及身份上的道德优越感,最终都投了赞成票。
这让我想起了业务上推动策略,如果你想推一件事,而老板和公司在关心另一个重心,可以像这个法案一样,找到两件事的共同点,先把这些共同点做到,再做剩下的,就水到渠成了,而不能只关心自己的想法和工作本身,了解局面非常关键。
/20260119104056680.png)
/20260119104056689.png)
/20260119104056661.png)
/20260119104056659.png)
/20260119104056707.png)
/20260119104056673.png)