- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
。
正文 。
现代互联网系统,架构设计时避不开的一点就是流量规划、负载均衡。 期望做到透明、多级的分流系统 。 “ 多级 ”就是在各个层面的技术组件来分流,“ 透明 ”就是业务无感知(甚至是技术无感知)。本文期望能够给各位架构师作为扫盲贴使用.
两条普适性原则:
作为架构师,想一想应对大流量互联网系统,我们有哪些可以优化的地方?扩带宽?服务器/组件横向扩容?做缓存?基本思路如下图所示:
。
。
客户端缓存(Client Cache):HTTP 协议的无状态性决定了它必须依靠客户端缓存来解决网络传输效率上的缺陷。包含三种缓存机制:“状态缓存”、“强制缓存”(“强缓存”)和“协商缓存”.
是指不经过服务器,客户端直接根据缓存信息对目标网站的状态判断。例如:301/Moved Permanently(永久重定向) 。
客户端可以无须经过任何请求,在指定时点前一直持有和使用该资源的本地缓存副本.
Expires 是 HTTP/1.0 协议中开始提供的 Header,后面跟随一个截至时间参数。当服务器返回某个资源时带有该 Header 的话,意味着服务器承诺截止时间之前资源不会发生变动,浏览器可直接缓存该数据,不再重新发请求,示例:
HTTP/1.1 200 OK
Expires: Wed, 8 Apr 2020 07:28:00 GMT
受限于客户端的本地时间.
无法处理涉及到用户身份的私有资源.
无法描述“ 不 缓存”的语义.
HTTP/1.1 200 OK Cache-Control: max-age=600
基于检测的缓存机制,通常被称为“协商缓存”。协商缓存有两种变动检查机制,分别是根据资源的 修改时间 进行检查,以及根据 资源唯一标识 是否发生变化来进行检查,它们都是靠一组成对出现的请求、响应 Header 来实现的:
如果此时服务端发现资源在该时间后没有被修改过,就只要返回一个 304/Not Modified 的响应即可,无须附带消息体,达到节省流量的目的,如下所示:
HTTP/1.1 304 Not Modified
Cache-Control: public, max-age=600
Last
-Modified: Wed, 8 Apr 2020 15:31:30 GMT
如果此时服务端发现资源在该时间之后有变动,就会返回 200/OK 的完整响应,在消息体中包含最新的资源,如下所示:
HTTP/1.1 200 OK Cache-Control: public, max-age=600 Last -Modified: Wed, 8 Apr 2020 15:31:30 GMT Content
如果此时服务端计算后发现资源的唯一标识与上传回来的一致,说明资源没有被修改过,就只要返回一个 304/Not Modified 的响应即可,无须附带消息体,达到节省流量的目的,如下所示:
HTTP/1.1 304 Not Modified
Cache-Control: public, max-age=600
ETag:
"28c3f612-ceb0-4ddc-ae35-791ca840c5fa"
如果此时服务端发现资源的唯一标识有变动,就会返回 200/OK 的完整响应,在消息体中包含最新的资源,如下所示:
HTTP/1.1 200 OK Cache-Control: public, max-age=600 ETag: "28c3f612-ceb0-4ddc-ae35-791ca840c5fa" Content
Etag是 HTTP 中一致性最强的缓存机制,又是 HTTP 中性能最差的缓存机制.
域名缓存(DNS Lookup):DNS 也许是全世界最大、使用最频繁的信息查询系统,如果没有适当的分流机制,DNS 将会成为整个网络的瓶颈。DNS的核心作用就是把域名解析成IP地址。典型的DNS域名解析流程如下图:
。
流量从客户端往服务器传输,这个过程就是“ 传输链路 ”。程序发出的 请求能否与应用层、传输层协议提倡的方式相匹配 ,对传输的效率也会有极大影响 。由于HTTP 协议还在持续发展,从 20 世纪 90 年代的 HTTP/1.0 和 HTTP/1.1,到 2015 年发布的 HTTP/2,再到 2019 年的 HTTP/3,由于 HTTP 协议本身的变化,使得“适合 HTTP 传输的请求”的特征也在不断变化。变化如下图:
。
HTTP( HTTP/3 以前)是以 TCP 为传输层的应用层协议。 减少请求数量 和 扩大并发请求数 成为了优化的主流思想.
。
核心:
“ 快速 UDP 网络连接 ”(Quick UDP Internet Connections,QUIC):以 UDP 协议为基础,由自己来实现可靠传输能力,并专门支持移动设备的网络切换场景。QUIC 提出了连接标识符的概念,该标识符可以 唯一地标识客户端与服务器之间的连接 ,而无须依靠 IP 地址。这样,切换网络后,只需向服务端发送一个包含此标识符的数据包即可重用既有的连接。2018 年末,IETF 正式批准了 HTTP over QUIC 使用 HTTP/3 的版本号,将其确立为 最新一代的互联网标准 .
截止到2023.2.21,根据 W3Techs 的数据显示,全球网站中,支持HTTP/2 协议占 39.8%,HTTP/3协议占25.2%.
内容分发网络(Content Distribution Network),即CDN是一种十分古老而又十分透明,没什么存在感的分流系统,许多人都说听过它,但真正了解过它的人却很少。一个运作良好的内容分发网络,能为互联网系统解决跨运营商、跨地域物理距离所导致的时延问题,能为网站流量带宽起到分流、减负的作用。举个例子,如果不是有遍布全国乃至全世界的阿里云CDN网络支持,哪怕把整个杭州所有市民上网的权力都剥夺了,把带宽全部让给淘宝的机房,恐怕也撑不住全国乃至全球用户在双十一期间的疯狂“围殴”。内容分发网络的工作过程,主要涉及路由解析、内容分发、负载均衡和所能支持的 CDN 应用内容四个方面,我们来逐一了解.
前面第二节讲解了DNS的路由解析,这里扩展一下有CDN参与的过程,核心就是生成了 CNAME (Canonical Name规范名)记录。实际上有2条记录:
。
如下图:
CDN 路由解析的具体工作过程是:
架设好“hello .com ”的服务器后,将服务器的 IP 地址在CDN服务商上注册为“源站”,注册后你会得到一个 CNAME( Canonical Name规范名 ),DNS 服务商会注册一条 CNAME 记录.
当第一位用户来访你的站点时,将首先发生一次未命中缓存的 DNS 查询, 域名服务商解析出 CNAME (“ hello .cdn.com ”) 后,返回给本地 DNS.
本地 DNS 查询 CNAME 时,由于能解析该 CNAME 的权威服务器只有 CDN 服务商所架设的权威 DNS ,这个 DNS 服务将根据一定的均衡策略和参数,如拓扑结构、容量、时延等,在全国的 CDN 缓存节点中挑选一个最适合的,将 IP 给本地 DNS.
浏览器从本地 DNS 拿到 IP 地址,访问CDN服务器。有缓存直接返回,没缓存访问源站再缓存返回.
CDN 获取源站资源的过程被称为“内容分发”,这是 CDN 的核心价值。目前主要有以下两种主流的内容分发方式:
内容分发网络最初是为了快速分发静态资源而设计的,但今天的 CDN 所能做的事情已经远远超越了开始建设时的目标,列举如下:
负载均衡(Load Balancing):调度后方的多台机器,以统一的接口对外提供服务,承担此职责的技术组件被称为“负载均衡”。从形式上来说都可以分为两种: 四层负载均衡和七层负载均衡 。维基百科上对 OSI 七层模型的介绍如下图:
Layer层级 | Protocol data unit (PDU) 协议数据单元 | 功能 | 流量在哪负载均衡 | ||
主机层(Host Layers) | 7 | 应用层 Application Layer |
数据 Data |
提供为应用软件提供服务的接口,用于与其他应用软件之间的通信。典型协议: HTTP、HTTPS 、FTP、Telnet、SSH、SMTP、POP3 等 | Nginx、Kong等。 |
6 | 表达层 Presentation Layer |
把数据转换为能与接收者的系统格式兼容并适合传输的格式。 | 主机。 | ||
5 | 会话层 Session Layer |
负责在数据传输中设置和维护计算机网络中两台计算机之间的通信连接。 | 主机。 | ||
4 | 传输层 Transport Layer |
Segment 数据段, Datagram 数据报 | 把传输表头加至数据以形成数据包。传输表头包含了所使用的协议等发送信息。典型协议: TCP、UDP 、RDP、SCTP、FCP 等 | 主机。协议里包含了主机的 port端口 号,如果说IP确定了互联网上主机的位置,那么port指向该主机上监听该端口的程序. |
|
媒体层(Media Layers) | 3 | 网络层 Network Layer |
数据包 Packet |
决定数据的传输路径选择和转发,将网络表头附加至数据段后以形成报文(即数据包)。典型协议: IPv4/IPv6 、IGMP、ICMP、EGP、RIP 等 | 路由器 ,设备之间依靠 IPv4/IPv6地址寻址 。网络包可以跨越LAN子网,在整个WAN广域网上通信了(比如 internet)。 |
2 | 数据链路层 Data Link Layer |
数据帧 Frame |
负责点对点的网络寻址、错误侦测和纠错。当表头和表尾被附加至数据包后,就形成数据帧(Frame)。典型协议:WiFi(802.11)、Ethernet(802.3)、PPP 等。 | 交换机 ,设备之间依靠 MAC地址寻址 。同一个LAN里面的设备可以相互通信。 | |
1 | 物理层 Physical Layer |
比特流 Bit |
在物理网络上传送数据帧,它负责管理电脑通信设备和网络媒体之间的互通。包括了针脚、电压、线缆规范、集线器、中继器、网卡、主机接口卡等。 | 网卡、电缆光纤,设备之间需要靠交叉线进行直连通信。 |
看了上图后,就可以清晰理解L4/L7负载均衡的概念:
负载均衡器在转发请求过程中 直接修改帧的 MAC 目标地址 .
。
如上图,整个请求、转发、响应的链路形成一个“三角关系”,所以这种负载均衡模式也常被很形象地称为“ 三角传输模式 ”(Direct Server Return,DSR),也有叫“单臂模式”(Single Legged Mode)或者“ 直接路由”(Direct Routing) ,笔者觉得最后这个最贴切,一刀见血 .
两种模式:
保持原来的数据包不变,新创建一个数据包, 把原来数据包的 Headers 和 Payload 整体作为另一个新的数据包的 Payload ,在这个 新数据包的 Headers 中写入真实服务器的 IP 作为目标地址 ,然后把它发送出去。设计者给这种“套娃式”的传输起名叫做“ IP 隧道 ”(IP Tunnel)传输,也还是相当的形象.
即 网络地址转换 (Network Address Translation)。直接 把数据包 Headers 中的目标地址改掉,请求转发给真实服务器 ,并响应给均衡器, 由均衡器把应答包的源 IP 改回自己的 IP,再发给客户端 ,这样才能保证客户端与真实服务器之间的正常通信.
四层负载均衡(L4)工作模式都属于“转发” ,即直接将承载着 TCP 报文的底层数据格式(IP 数据包或以太网帧)转发到真实服务器上,此时客户端到响应请求的真实服务器维持着同一条 TCP 通道。但工作在四层之后(L7)的负载均衡模式就无法再进行转发了, 只能进行代理 ,此时真实服务器、负载均衡器、客户端三者之间由两条独立的 TCP 通道来维持通信,转发与代理的区别如下图所示.
。
七层负载均衡器它就属于反向代理中的一种 。网络性能不如四层负载均衡器,但它工作在应用层,可以感知应用层通信的具体内容,能够做出更智能的决策.
常见的均衡策略如下:
缓存(Cache):软件开发中的缓存并非多多益善, 它有收益,也有风险 。服务端缓存大体可分为两类:
tip:总监级岗位需要关注的东西:硬件提升和缓存带来的风险,需要做一个均衡考量.
通常,我们设计或者选择缓存至少会考虑以下四个维度的属性:
根据 Caffeine 给出的一组目前业界主流进程内缓存实现方案,包括有 Caffeine、ConcurrentLinkedHashMap、LinkedHashMap、Guava Cache、Ehcache 和 Infinispan Embedded 的对比,从 Benchmarks 中体现出的它们在 8 线程、75%读操作、25%写操作下的吞吐量来看,各种缓存组件库的性能差异还是十分明显的,最高与最低的相差了足有一个数量级,如下图所示.
。
。
在 Caffeine 的实现中,设有专门的 环形缓存区 (Ring Buffer,也常称作 Circular Buffer)来记录由于数据读取而产生的状态变动日志。为进一步减少竞争,Caffeine 给每条线程(对线程取 Hash,哈希值相同的使用同一个缓冲区)都设置一个专用的环形缓冲。所谓环形缓冲,并非 Caffeine 的专有概念,它是一种拥有 读、写两个指针的数据复用结构 ,在计算机科学中有非常广泛的应用。Ring Buffer原理如下图:
。
。
最基础的淘汰策略实现方案有以下三种:
近年来提出的 TinyLFU 和 W-TinyLFU 算法:
Caffeine 官方给出的 W-TinyLFU 以及另外两种高级淘汰策略 ARC (Adaptive Replacement Cache)、 LIRS (Low Inter-Reference Recency Set)与基础的 LFU 策略之间的对比,如下图所示.
。
一般来说,一套标准的 Map 接口(或者来自 JSR 107 的 javax.cache.Cache 接口)就可以满足缓存访问的基本需要,不过在“访问”之外,专业的缓存往往还会提供很多额外的功能。笔者简要列举如下:
几款主流进程内缓存方案对比结果如下图:
。
复制式缓存 :复制式缓存可以看作是“能够支持分布式的进程内缓存”,读取数据时直接从当前节点的进程内存中返回,理论上可以做到与进程内缓存一样高的读取性能;当数据发生变化时,就必须遵循复制协议,将变更同步到集群的每个节点中,复制性能随着节点的增加呈现平方级下降.
集中式缓存 :集中式缓存是 目前分布式缓存的主流形式 ,集中式缓存的读、写都需要网络访问,其好处是不会随着集群节点数量的增加而产生额外的负担,其坏处是读、写都不再可能达到进程内缓存那样的高性能。典型案例就是Redis.
分布式缓存与进程内缓存各有所长,也有各有局限,它们是互补而非竞争的关系,如有需要,完全可以同时把进程内缓存和分布式缓存互相搭配,构成透明多级缓存(Transparent Multilevel Cache,TMC),如下图所示:
。
。
概念:缓存中没有,数据库中也没有,这种查询不存在数据的现象被称为缓存穿透.
解决方案:
概念:如果缓存中某些热点数据忽然 因某种原因失效 了,譬如典型地由于超期而失效,请求未能命中缓存,都 到达真实数据源 中去,导致其压力剧增,这种现象被称为缓存击穿.
解决方案:
概念:缓存击穿是针对单个热点数据失效, 缓存雪崩是大批量缓存数据失效给数据源带来压力 .
解决方案:
概念:存污染是 指缓存中的数据与真实数据源中的数据不一致 的现象.
解决方案:
了尽可能的提高使用缓存时的一致性,已经总结不少更新缓存可以遵循设计模式,譬如 Cache Aside、Read/Write Through、Write Behind Caching 等。其中最简单、成本最低的 Cache Aside 模式 是指:
Cache Aside 模式 依然是 不能保证在一致性上绝对不出问题 的。先写数据源再删缓存,也可能有问题:如果 写入成功,缓存未删除,导致DB和cache不一致 。第二种几率很小,可以使用MQ重试机制解决,实现最终一致性.
。
。
。
。
。
。
=====参考========= 。
http://icyfenix.cn/architect-perspective/general-architecture/diversion-system/ 。
最后此篇关于透明多级分流系统(架构扫盲贴)的文章就讲到这里了,如果你想了解更多关于透明多级分流系统(架构扫盲贴)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
AOP 是 Spring 体系中非常重要的两个概念之一(另外一个是 IoC),今天这篇文章就来带大家通过实战的方式,在编程猫 SpringBoot 项目中使用 AOP 技术为 controller 层
我是一名优秀的程序员,十分优秀!