逻辑层:
可扩展:(注①):
水平扩展(冗余部署,防单点)
垂直扩展(提升处理能力,增加内存磁盘等)
隔离:避免单一业务占用全部资源;避免业务之间的相互影响 (注②)
解耦:剥离非核心业务,如用异步消息解耦。
RPC:(注③)
RPC框架:dubbo(阿里java框架)、thrift(apache开源)、gRPC、rpcx(go版dubbo)
微服务restful框架:Spring Boot/Cloud(netflix)(注④)
同步、异步:
连接池:
消息队列:(注⑤)
消息队列中间件:RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、Redis消息队列
延迟计算:( 注⑥ )
注⑥ :我也不确定他说的是不是python中的惰性计算 (迭代器的进化版-->生成器)
让程序的计算发生在真正使用到的时候,而不是提前计算好所有数据,因为有些场景下,并不是所有数据都会用到(比如棋局游戏,没必要计算所有的步骤)
数据预读
轮询通知
事件触发器
模块化
注释:
注①: 水平扩展与垂直扩展
垂直扩展:提升单机处理能力。
1.增强单机硬件性能例如:增加CPU核数如32核,升级更好的网卡如万兆,升级更好的硬盘如SSD,扩充硬盘容量如2T,扩充系统内存如128G;
2.提升单机架构性能,例如:使用Cache来减少IO次数,使用异步来增加单服务吞吐量,使用无锁数据结构来减少响应时间。
水平扩展:只要增加服务器数量,就能线性扩充系统性能。水平扩展对系统架构设计是有要求的,如何在架构各层进行可水平扩展的设计,以及互联网公司架构各层常见的水平扩展实践,是本文重点讨论的内容。
提升单机处理能力的方式是最快的,但是单机性能有极限。所以互联网分布式架构设计高并发终极解决方案还是水平扩展。

反向代理层的水平扩展:(上文提到过的dns负载均衡)

反向代理层的水平扩展,是通过“DNS轮询”实现的:dns-server对于一个域名配置了多个解析ip,每次DNS解析请求来访问dns-server,会轮询返回这些ip。
当nginx成为瓶颈的时候,只要增加服务器数量,新增nginx服务的部署,增加一个外网ip,就能扩展反向代理层的性能,做到理论上的无限高并发。
站点层的水平扩展:

站点层的水平扩展,是通过“nginx”实现的。通过修改nginx.conf,可以设置多个web后端。
当web后端成为瓶颈的时候,只要增加服务器数量,新增web服务的部署,在nginx配置中配置上新的web后端,就能扩展站点层的性能,做到理论上的无限高并发。
服务层的水平扩展:

站点层通过RPC-client调用下游的服务层RPC-server时,RPC-client中的连接池会建立与下游服务多个连接,当服务成为瓶颈的时候,只要增加服务器数量,新增服务部署,在RPC-client处建立新的下游服务连接,就能扩展服务层性能,做到理论上的无限高并发。如果需要优雅的进行服务层自动扩容,这里可能需要配置中心里服务自动发现功能的支持。
数据层的水平扩展
在数据量很大的情况下,数据层(缓存,数据库)涉及数据的水平扩展,将原本存储在一台服务器上的数据(缓存,数据库)水平拆分到不同服务器上去,以达到扩充系统性能的目的。
注②: 高并发之隔离
线程隔离:把请求分类,然后交给不同的线程池处理

进程隔离:将系统拆分为多个子系统来实现物理隔离。通过进程隔离使得某一个子系统出现问题不会影响到其他子系统

集群隔离:
随着系统的发展,单实例服务无法满足需求了,此时需要服务化技术,通过部署多个服务,形成服务集群来提升系统容量

随着调用方的增多,当秒杀服务被刷会影响到其他服务的稳定性,此时应该考虑为秒杀提供单独的服务集群,即为服务分组,从而当某一个分组出现问题不会影响到其他分组,从而实现了故障隔离

读写隔离:redis主从集群
动静隔离:页面静态化
热点隔离:将秒杀抢购之类的活动提前单独隔离
注③:RPC(远程服务调用)
假设我有一个计算器接口Calculator,以及它的实现类CalculatorImpl,那么在系统还是单体应用时,你要调用Calculator的add方法来执行一个加运算,直接new一个CalculatorImpl,然后调用add方法就行了,这其实就是非常普通的本地函数调用,因为在同一个地址空间,或者说在同一块内存,所以通过方法栈和参数栈就可以实现
现在,基于高性能和高可靠等因素的考虑,你决定将系统改造为分布式应用,将很多可以共享的功能都单独拎出来,比如上面说到的计算器,你单独把它放到一个服务里头,让别的服务去调用它。那么这下问题来了,服务A里头并没有CalculatorImpl这个类,那它要怎样调用服务B的CalculatorImpl的add方法呢?
方案一:仿照B/S架构,暴露一个resful接口
方案二:代理模式。结合Spring IoC一起使用,通过Spring注入calculator对象,注入时,如果扫描到对象加了@Reference注解,那么就给它生成一个代理对象,将这个代理对象放进容器中。而这个代理对象的内部,就是通过httpClient来实现RPC远程过程调用的。(感觉像是依赖注入,不是很理解这段)如阿里的Dubbo
总结:RPC要解决的两个问题:
解决分布式系统中,服务之间的调用问题。
远程调用时,要能够像本地调用一样方便,让调用者感知不到远程调用的逻辑。
注④:RPC vs Restful
其实这两者并不是一个维度的概念,总得来说RPC涉及的维度更广。
如果硬要比较,那么可以从RPC风格的url和Restful风格的url上进行比较。
比如你提供一个查询订单的接口,用RPC风格,你可能会这样写:/queryOrder?orderId=123
用Restful风格呢?Get /order?orderId=123
RPC是面向过程,Restful是面向资源,并且使用了Http动词。从这个维度上看,Restful风格的url在表述的精简性、可读性上都要更好。
注⑤:主流mq对比 《明哥rebbitMQ文集》

网友评论