目录
IaaS(Infrastructure as a Service):基础设施即服务
PaaS(Platform as a Service):平台即服务
SaaS(Software as a Service):软件即服务
高并发(High Concurrency)是互联网分布式系统架构设计中必须考虑的因素之一。当多个进程或线程同时(或着说在同一段时间内)访问同一资源时会产生并发问题,因此需要通过专门的设计来保证系统能够同时(并发)正确处理多个请求。
简单地说,高性能(High Performance)就是指程序处理速度快、耗能少。与性能相关的一些指标如下:
高并发和高性能是紧密相关的,提高应用的性能,可以提高系统的并发能力。
应用性能优化时,对于计算密集型和 I/O 密集型还是有很大差别,需要分开来考虑。
水平扩展(Scale Out):只要增加服务器数量,就能线性扩充系统性能。通常增加服务器资源(CPU、内存、服务器数量),大部分时候是可以提高应用的并发能力和性能 (前提是应用能够支持多任务并行计算和多服务器分布式计算才行)。但水平扩展对系统架构设计是有要求的,难点在于:如何在架构各层进行可水平扩展的设计。
高可用性(High Availability)通常用来描述一个系统经过专门的设计,从而减少停工时间,保证服务的持续可用。
如高可用性集群就是保证业务连续性的有效解决方案。
硬件/系统级别的解决方案:
应用级别的解决方案:
随着业务的不断增加,服务器性能很快又到达瓶颈。不管是提升单机硬件性能,还是提升单机架构性能,都有一个致命的不足:单机性能总是有极限的。所以互联网系统架构对高性能的解决方案还是水平扩展。
DNS(Domain Name System,域名系统),因特网上作为域名和 IP 地址相互映射的一个分布式数据库,能够使用户更方便地访问互联网,而不用去记住能够被机器直接读取的 IP 数串。通过主机域名得到该域名对应的 IP 地址的过程叫做域名解析。DNS 协议运行在 UDP 协议之上,使用端口号 53。
循环复用 DNS 是一个普遍使用的在 Web 服务器上负载均衡的解决方案。
http://www.company.cn : 192.168.1.100 192.168.1.101 192.168.1.102
弊端:循环复用 DNS 将传入的 IP 请求映射到定义的一系列循环形式的服务器。一旦其中的服务器发生故障,循环复用 DNS 会继续把请求发送到这个故障服务器,直到把该服务器从 DNS 中移走为止。在这之前,许多用户必须等到 DNS 连接超时以后才能成功地访问目标网站(正常运行的服务器)。
由于现有系统的各个核心部分随着业务量、访问量和数据流量的快速增长,其处理能力和计算强度也需要相应地增大,使得单一的服务器设备根本无法承担。在此情况下,如果扔掉现有设备去做大量的硬件升级,这样将造成现有资源的浪费,而且如果再面临下一次业务量的提升时,这又将导致再一次硬件升级的高额成本投入,甚至性能再卓越的设备也不能满足当前业务量增长的需求。
针对此情况而衍生出来的一种廉价、有效、透明的方法以扩展现有网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性的技术就是负载均衡(Load Balance)。
Apache 是世界使用排名第一的 Web 服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的 Web 服务器端软件。
JK 则是 apache 提供的一款为解决大量请求而分流处理的开源插件。
Nginx 是一款轻量级的反向代理服务器,由俄罗斯的程序设计师 Igor Sysoev(伊戈尔·西索夫)所开发,供俄国大型的入口网站及搜索引擎 Rambler(漫步者)使用。
Nginx 特点是占有内存少,并发能力强,事实上 Nginx 的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用 Nginx 的网站用户有腾讯、新浪、网易等。
修改 nginx.conf 的配置项:
server { listen 80; server_name nginx-01.itcast.cn; # nginx 服务器的主机名 # 反向代理的配置 location / { root html; proxy_pass http://192.168.0.21:8080; # 代理走向的目标服务器(tomcat) } }
动态资源:
location ~ .*\.(jsp|do|action)$ { proxy_pass http://tomcat-01.itcast.cn:8080; }
静态资源:
location ~ .*\.(html|js|css|gif|jpg|jpeg|png)$ { expires 3d; }
在 http 配置项中,跟在 upstream 后面的名字可以随意取,但是要和 location 下 proxy_pass http:// 后的组号保持一致。
http { upstream tomcats { server shizhan02:8080 weight=1; # weight 表示轮询权重 server shizhan03:8080 weight=1; server shizhan04:8080 weight=1; } # 动态资源配置 location ~ .*\.(jsp|do|action) { proxy_pass http://tomcats; #tomcats是后端服务器组的逻辑组号 } }
Keepalived 是一个基于 VRRP 协议来实现的 WEB 服务高可用方案,可以利用其来避免单点故障。
Keepalived 主要用作?Web 服务器的健康状态检查,以及负载均衡主服务器和备服务器之间 Failover(失效转移)的实现。
Keepalived?通常部署在 2 台服务器上,分为一主(Master)一备(Backup),但是对外表现为一个虚拟 IP。Keepalived 可以对本机上的进程进行检测,一旦 Master 检测出某个进程出现问题,就会将自己切换成 Backup 状态,然后通知另外一个节点切换成 Master 状态。
LVS 的英文全称是 Linux Virtual Server,即 Linux 虚拟服务器,是一个虚拟的服务器集群系统,本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的开源软件之一。在 Linux 内核 2.6 中,它已经成为内核的一部分,在此之前的内核版本则需要重新编译内核。
优点:
缺点:
LVS 对比 Nginx:
LVS 总共有三种代理方式:
所有的连接都要经过 LVS,所以这种负载方式是有流量限制的,具体能撑起多大的流量跟机器有关。
我们可以发现 LVS 只对 Request 连接进行了负载,而 Response 直接通过 Real Server 发送到 Client(LVS 通过修改源/目标 IP 实现)。但是,Request 的时候应该也有流量啊,为什么说它没有流量产生呢?等介绍完第三种负载策略,我们放在后面一起讨论。
我们发现它的工作原理图和 IP Tunneling 很像:Request 通过 LVS 进行转发,然后 Real Server 直接将 Response 发送给 Client。
只是有一点不同,图中说了 LVS 和 Real Server 需要在同一个网段上(Must be in a physical segment)。
? ? ? ? ? ? ?
注意上图中的三角链路:由 LVS 转发的用户请求,再经 Nginx 转发 Real Server 处理完请求后,直接通过 Nginx 将响应返回给用户。
?
CDN:全称是 Content Delivery Network,即内容分发网络,也称为内容传送网络。CDN 是构建在现有网络基础之上的智能虚拟网络,依靠部署在各地的边缘服务器,通过中心平台的负载均衡、内容分发、调度等功能模块,使用户就近获取所需内容,降低网络拥塞,提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。
CDN 的基本原理是广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应用户请求。
CDN 的基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输的更快、更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础之上的一层智能虚拟网络,CDN 系统能够实时地根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息,将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决 Internet 网络拥挤的状况,提高用户访问网站的响应速度。
Mysql
Oracle
当访问用户越来越多,写请求暴涨,对于上面的单 Master 节点肯定扛不住,那么该怎么办呢?多加几个 Master?不行,这样会带来更多的数据不一致的问题,且增加系统的复杂度。那该怎么办?就只能对库表进行拆分了。
常见的拆分类型有垂直拆分和水平拆分。
以拼夕夕电商系统为例,一般有订单表、用户表、支付表、商品表、商家表等,最初这些表都在一个数据库里。后来随着砍一刀带来的海量用户,拼夕夕后台扛不住了!于是紧急从阿狸粑粑那里挖来了几个 P8、P9 大佬对系统进行重构。
由于垂直分库已经按照业务关联切分到了最小粒度,但数据量仍然非常大,于是 P9 大佬开始水平分库,比如可以把订单库分为订单 1 库、订单 2 库、订单 3 库……那么如何决定某个订单放在哪个订单库呢?可以考虑对主键通过哈希算法计算放在哪个库。
分完库,单表数据量任然很大,查询起来非常慢,P9 大佬决定按日或者按月将订单分表,叫做日表、月表。
分库分表同时会带来一些问题,比如平时单库单表使用的主键自增特性将作废,因为某个分区库表生成的主键无法保证全局唯一,这就需要引入全局 UUID 服务了。
经过一番大刀阔斧的重构,拼夕夕恢复了往日的活力,大家又可以愉快的在上面互相砍一刀了。
在代码层面实现分库分表逻辑:
使用分布式/分库分表的中间件:
使用分布式数据库:
传统架构(单体架构)的劣势:
将单个大型系统,解耦拆分成各子模块系统。
继续将系统架构进行分层,且下图中每一列实时链路分别属于所在地的数据中心,假如此时用户从 A 地(如北京市)跑到了 B 地(如深圳市)使用服务,那么两地间的用户数据同步及跨地访问服务将产生效率问题。
策略:如下图所示,用户每一次访问服务仅使用所在地的实时链路。这样虽然牺牲了用户在短暂逗留地区的访问效率,但保证了用户在主要居住地的服务/数据访问效率。
如某用户主要居住在北京市,平时在查看个人历史数据时访问效率快,而在其他区域(如在深圳市)查看个人历史数据时则可能需要等待多转几个圈的加载时间。
服务网格是一种将服务治理能力(比如:服务路由、安全、可观测性、限流熔断等)下沉到基础设施的架构。让业务更专注于业务开发,而由微服务架构引入的问题,交给基础设施去解决。
第一代微服务的常见架构(SpringCloud/Dubbo)如下图所示:
在黄色的容器内有服务 A、服务 B。A 和 B 都包含自己的业务逻辑,如果想要 A 调用 B,同时试图对这个服务进行治理,通常会在业务的内部集成一个 SDK,来实现服务发现、负载均衡、服务路由、重试、熔断限流等功能。
但是,这个架构存在三个主要问题:
ServiceMesh(服务网格)解决了当前架构的哪些痛点 ?
这种架构实现了服务治理技术和业务逻辑的解耦,是云原生时代微服务治理技术的发展方向,也得到了越来越多的公司的关注。