系统架构:流量入口&服务治理&数据选型

您所在的位置:网站首页 h5入口是什么 系统架构:流量入口&服务治理&数据选型

系统架构:流量入口&服务治理&数据选型

2023-12-19 09:34| 来源: 网络整理| 查看: 265

「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」

 

一般来说,我们介绍自己做的项目的一个系统架构方案,都要分两个基本的维度去介绍,才不至于让面试官觉得你的思维混乱。

 

第一个维度是系统架构维度,作为系统架构师,我们介绍对应的系统架构维度的时候,一定要体现整体的一个项目的部署结构以及你做的一个选型的思考。

 

然后你可以介绍一下你的一个业务架构,包含了业务场景方面的一个引入,来做你业务架构的一个设计。

系统架构

 

我们首先来看一下你的一个系统架构,一般来说系统架构我们需要分三层去做对应的一个介绍:

 

第一层,是你的流量入口是如何引入、如何做管理。

 

第二层,是你的核心服务层,如何做到一个服务治理相关的一个功能。

 

第三层,是你最最容易产生瓶颈的数据选型是如何做的。

 

接下来就让我带大家一起来看一下我们系统架构的能力。

 

那在整个的面试的过程当中,你千万一定要让面试官能够清楚地理解到你的一个系统架构,一般来说,用言语去描述对应的一个内容是最不靠谱的,因为这非但不能很快速的让面试官理解你的系统架构能力,反而会对你的面试造成负面的影响。

 

因此在介绍你的系统架构能力的时候,面试官一般会主动要求你在白板上或者给你一张纸,要求你去画一下你的系统的流程。

 

如果说面试官没有给你对应的白板和纸要求你口述的话,你也最好礼貌地让面试官可以给你呈现的一个工具或者平台。

 

假定我们现在处于一个面试的环境当中,你要去画一下系统架构。

流量入口层

首先我们要关注的是一个流量入口层,那一般来说我们对应的一个应用都会是前后端分离的一个项目。

 

因此我们可以假定我们对应的前端是一个 H5 页面,一般来说 H5 页面都需要加载它的一个静态资源文件,于是我们会把静态资源文件放在我们的 CDN 服务器当中,让 H5 页面可以通过 CDN 去加载我们前端的静态文件。

 

然后我们的 CDN 由于边缘的一个缓存节点服务,因此它背后应该有一个源站的地址。我们一般来说就都会将源站的文件系统放在一个 Nginx 的静态文件目录下面。于是我们就有一个 Nginx 静态资源站源服务器。

 

对应的一个静态的源站资源服务器内部的话,其实就是它的一个磁盘文件系统,所有跟静态资源相关的文件系统都会挂在这个磁盘文件当中。

 

如果说当我们的用户是第一次访问这个 CDN 的边缘节点,它会发现没有对应的缓存的 cache 被命中之后,就会有往对应的静态资源服务器回源的一个动作。

 

以上就是静态资源的一个流量入口。

 

那然后我们来看一下我们对应的动态资源的流量入口是一个什么样的。

 

一般来说面试者都会讲,我们会把动态请求直接通过 Nginx 反向代理给我们的 H5 的一个前端的服务。并不是说这样的一个架构不是很好,但是现在我们大部分的公司都会采取 CDN 去代理动态请求这样的一个能力。

 

可能有的会问,我为什么 CDN 明明不是代理这样的一个静态资源文件去做一个缓存 cache 的,为什么仍然会有代理动态请求的一个过程呢?

 

那试想一下,假定我们现在会出现这样的一个情况,如果说我们没有 CDN 的话,我们直接通过一个 Nginx 的反向代理服务器去控制我们的流量入口,会发生什么?

 

现在假想一下,这里有一个 Nginx 反向代理服务器。当然一般公司除了会用这个 Nginx 的反向代理之外,还会配上一个 LVS 作为四层的一个代理模型,然后会有 Nginx 的多台的反向代理服务器去跨公司内网、去承载对应的一个流量。

 

这个 LVS 服务器可以通过网络层的一个代理去代理这四台对应的 LVS 代理 Nginx 反向服务器。

 

如果说我们对应的这个 LVS 直接暴露一个公网 IP 给到我们的 H5 页面,去直接访问它对应的这个 LVS 的这个内容,我们来看一下这样的架构会不会有什么样的问题。

 

首先我们针对这样架构,由于 LVS 暴露的是公网的 IP,我们不可能在 H5 的页面里去写公网的 IP。

 

一般来说我们都会配置域名,也就是我们会通过 DNS 服务器去配置公网 IP 的一个记录的映射。

 

这样的话我们的 H5 页面访问 DNS 的时候,其实是要查询我的一个 LVS + 反向代理服务器在公网当中的一个 IP 的配置。

 

那试想一下,由于这个 LVS 的节点是作为全局的流量入口的一个配置,如果说这个 LVS 代表了我这个机房的一个出入的时候发生了任何的异常情况,例如整个这个机房崩溃,导致这个 LVS 流量入口的外网的一个请求无法被这个 H5 页面访问到,那这个时候就会是灾难性的。

 

因此一般的公司都会采用双机房的部署配置,那什么是双机房呢?

 

我们假设我们公司是双机房的配置,也就是有一个 A 机房 LVS1,另外还有一个 B 机房 LVS2,它们是两个独立的这样的一个公网的 IP 地址。

 

这个时候我们来看一下,如果我们 H5 的页面访问 LVS1 的公网 IP 地址,请求它内部的流量入口的一个代理服务。

 

这个时候发现流量、网络都是正常的,但是因为某一个瞬间,整个的这个机房网络产生对应的一个问题,我们这个 H5 的页面就无法访问这个 LVSA 对应的一个节点。

 

那我们需要做多机房融灾的时候,我们需要把 H5 的整个一个页面的流量切换到 LVSB 上面,但是由于我们 DNS 的一个缓存域名和整个 LVSB 节点对应的一个内容之间是通过这个 DNS 的记录去查询的,我们只有通过运维人员手动的去修改 DNS 节点上面的对应的内容,将原本对应的一个域名地址,从公网 IP1 切换到公网 IP2,这个时候我们对应的 H5 页面才能掐断对应的这条连接,而转而去访问这台 LVSB,达到了一个机房容灾切换的配置。

 

但是这个时候我们往往可以看到对应的一个问题,首先 DNS 节点的一个更新其实是有缓存的一个时长的,也就是我们对应的这个 DNS 的记录的节点的更新,并没有办法实时地做对应的切换,而且 DNS 对应的一个切换,需要到控制台或者通过对应的 DNS 的 API 去做对应的一个修改,其往往时效性是比较差的,这个也是我们直接切换 DNS 的一个劣势。

 

到这里你可能会问,那这样的话我们到底应该怎么样子做,才能做到在一个可用性的环境下做一个快速切换呢?答案就是这个 CDN 节点。

 

然后如果说我们采用 CDN 这样的一个内容资源的话,就可以摒弃掉一些问题。

 

首先我们将所有的这个静态请求的一个解析不放给 DNS 服务器,而转交给我们对应的一个 CDN 服务商。

 

也就是说我们 H5 页面通过 DNS 解析请求对应的这个域名不是直接的这个公网 IP 地址,而是由这个 CDN 服务商给我们提供的内容的信息。

 

那这个时候我们 H5 的请求就会将对应的一个请求的内容转发给这个 CDN 服务器,然后由这个 CDN 服务器代替我们去做了一个流量的代理。也就是我们的 H5 页面并不是通过对应的 CDN 不只是去拿静态资源文件,而会去访问动态请求。

 

那这个时候就由我们的 CDN 去做一个流量的代理。那一般来说动态的请求是不能被 CDN 缓存的,那 CDN 往往我们把它定义为内容分发网络是有 cache 的功能,但我们仍然可以不配置 cache 的功能,而将所有的请求都设置为回源。

 

那它的回源地址的话可以就是这个公网 IP1。大家就可以看到,我们虽然在整个的这个请求链路上多加了一个 CDN 节点,但是就可以有一个快速切换的功能,为什么呢?

 

我们现在假设我们的 H5 页面通过 CDN 访问了 LVS1,如果说对应的这个 LVS1 背后的一个代理机房有任何的一个问题,那我们可以快速的在 CDN 层就将对应的这个 IP 切换成 LVS2 这个源站地址,那这个切换的话近乎可以算是瞬时的,只要我们 CDN 对应的一个配置可以快速的更新即可。

 

一般来说,现在我们的一些大公司都会采取这种样子的一个网络架构,同时也颠覆了 CDN 仅仅只能代理静态资源文件这样的一个问题,而是说我们的 CDN 也可以代理动态的请求,仅仅只不过动态请求的代理是没有 cache,但是是可以方便切换的,那这个就是我们现在所用到的电商的一个流量入口层的系统架构。

 

 

 

 

核心的服务治理层

 

接下来我们来看一下核心的服务治理层。

 

一旦对应的 H5 的前端流量的动态请求数据,通过 CDN + LVS + Nginx 的反向代理,代理到了我们的后端机房之后,我们就开启了内部的服务治理模式。

 

由于我们项目当中主要使用 Spring Cloud 相关的一些技术,所以说我们对应的主要项目当中应用到的都是 Spring Cloud 相关的组件。

 

那我们的项目的部署属于双机房模式,但是内部的服务却是机房之间隔离的,也就是我们对应的有一个商品服务,还有一个交易服务,它们都是基于 Spring Boot,内置 Tomcat 应用,通过 Spring Boot 的启动程序,启动起来之后,然后注册到我们对应的 Spring Cloud 的 Eureka Server 上,Eureka Server 是一个注册中心,然后由我们的一个所有网关去做 API Getaway 流量代理接入。

 

这样的话服务的一个内容就比较清晰了,也就是我们的动态请求通过 LVS + Nginx 的流量代理之后,进入到我们的 Zuul 网关。

 

由于 Zuul 网关和商品服务以及交易服务都同时注册到了 Eureka 配置注册中心当中,因此它可以做服务治理相关的一个流量。

 

当然内部我们仍然会使用类似于 hystrix 这样的一个熔断的功能,去做我们服务的一个熔断处理。

 

介绍到这里,面试官会问,我们所有的一个项目都会基于单机房部署,然后如果双机房的话就做服务隔离了。

 

其实也不尽然,还是有对应的一些大型的互联网公司采用的是多机房部署的模式,这样的话它的一个注册中心就要支持多机房部署的一个结构。

 

我们举个例子,我们现在是在对应的第二个机房里部署了单独的 Eureka 的配置中心 Server 和数据服务以及 Zuul 网关。

 

我们完全可以在对等的第一个机房也部署对应的一个服务的能力,也部署对应的 Zuul 网关。

 

但是由于我们的机房之间是需要做流量的调度,因此我们对应的 Eureka Server 肯定就只能有一个并且有流量调度的策略。

 

比如我们对应第二个机房进来的所有网关的流量的 60%是需要分流到对应的机房一的商品服务,40% 是需要分流到机房二的商品服务,这些都会在 Eureka 内部去做到对应的配置。

 

当然前提条件是原生的一个 Spring Boot + Spring Cloud 的一个结构并不能完全支持多机房的架构,我们还是需要去做一些改造的。

 

但是对应的这样的一个多机房的流量部署的结构,在某些程度上面会破坏整个机房的一个隔离性,导致了一些不可预知的一些问题。

 

因为跨机房之间的调用会产生网络问题,或者由于开发者的一个配置,导致了流量乱窜、查问题不方便,甚至引发线上事故。

 

因此大部分的公司虽然说采用的是这种样子的一个双机房的结构,但是每个机房还是会有自己的一个注册中心的配置,以及自己的一些隔离的服务,来保证整个的一个流量入口是通过 CDN 的域名去做 HTTP 进入的一个控制,而每个机房内部都是自己隔离的对应的一个服务。

 

这样的话有一个好处是仍然做到了一个服务的一致性,以及灾备当中的一个权衡。

 

数据层

 

最后我们再来看一下数据层,那数据是整个系统能力的一个核心,因为我们所有的服务层和流量代理层本质上来说都是无状态的服务。

 

那想要整个服务能够完成一个 OLTP 交易式的一个事物,我们就必须要有数据存储。

 

一般来说,数据存储主要分为三种类型,第一种类型就是我们最常见的关系型数据库。

 

在互联网当中,我们最最常用的就是 MySQL 数据库。于是在我们的电商体系架构内就会有一个 MySQL 数据集群,然后我们会有一些 NoSQL 相关的一些数据服务,类似于我们的搜索引擎做商品搜索,因此 ElasticSearch 毫无疑问的作为我们电商的一个商品服务的一个搜索系统的存储,去做能力的使用。

 

那最后为了达到整个的系统的一个容量以及 QPS 的吞吐,我们一般都会将服务加上缓存,我们采用的会是做 Redis 相关的一个缓存服务。

 

接下来来看一下我们的一个数据服务层在整个的运维架构体系内会以一个什么样的形式存在?

 

一般来说,我们的一个数据服务层、数据层由于是一个完完全全有状态的一个能力,所以说大部分的场景下,它只能做一个单机房的一个节点的部署,也就是我们 MySQL 的数据库。

 

我们所有的一个 MySQL 数据库都会落在一个主机房内,假设我们在整个的这个服务当中,主机房是第一个机房。

 

我们假定我们的主机房在没有产生任何灾备的情况下,是对应的机房 1。因此我们的一个 MySQL 服务就要为我们的商品服务和交易服务提供事物的存储的一个能力。

 

当然我们的机房 2 也必须得要以远程调用的一个方式去访问我们 MySQL 服务器。

 

自然而然,你可能就会想到,我对于数据服务来说的话,它的远程的一个专线访问往往是比较慢的,也是我们比较容易诟病的一个问题。

 

也就是说我们在多机房的一个部署结构当中,我们的一个数据存储到底应该以什么样的方式去做部署?

 

一般来说,单节点的一个部署方式是最最容易保持事物一致性的,因为没有数据来回同步的一个问题。

 

那我们试想一下,如果说我们对应的 MySQL 采取主从分布式的一个结构。

 

并且把它的存库部署到机房 2,让我们商品服务和交易服务在另外一个机房内读取对应的一个 MySQL 的从库,然后通过主从一致性的一个方案去做一个主从的备份。

 

试想一下,我们对应的第二个机房就没有办法对它的一个 MySQL 的重复做写操作,自然这样的一个问题就会落到应用层面,也就是我们机房二的应用是需要感知状态的,因为它只能做读操作,不能做写操作。

 

因此针对 MySQL 这种样子的一个事物一致性要求比较高的存储服务来说,去做这样的一个跨机房的部署往往是非常不划算的,因为我们机房是需要被感知数据状态,因此我们大部分的项目是不会采取对应的方案,仍然会采取我们单点部署的结构。

 

当然我们整个的 MySQL 的一个服务集群是可以做分库分表的,也就是可以把我们交易服务的用户订单以时间戳维度做分库分表,这样可以避免掉我们 MySQL 的数据无限制的膨胀,而是只以时间戳维度去做划分的话,会使得用户访问最近的数据,而如果要访问在之前的数据,可以到历史的数据库当中去做对应的一个查询,只需要在我们的交易服务内对 SQL 语句做一些改造即可。

 

搜索服务

 

然后来看一下我们的 ElasticSearch,ElasticSearch 的一个集群架构,本身就是可以支持多机房、多调用的。

 

因为 ElasticSearch 大部分场景下是提供搜索的一个只读功能,因此 ElasticSearch 是非常适合多机房部署的。

 

假定我们有两套 ElasticSearch 的集群,第一套服务于主机房,第二套服务于备用的机房,然后我们主机房的商品服务完全读取主机 ElasticSearch 的服务,我们主机房的商品服务读取主机房 ElasticSearch,而辅助机房第二个机房的商品服务读取第二个机房的 ElasticSearch。

 

然后 ElasticSearch 之间因为是两套集群所做的一个独立的运作,所以说我们会有索引的一个刷新服务,这个索引我们一般把它叫做 indexServer,也就是建立索引服务。

 

会通过主的 MySQL 的 binlog 去做两层索引的刷新,将对应的不同的索引都会刷到两个机房内,保证这两个机房的索引是在最终状态下是一致的。

 

那由于搜索服务并不是一个对事物要求强一致的服务,因此这两个 ElasticSearch 之间有延迟或者稍微有一些数据不一致,往往情况下是可以接受的。

 

缓存服务

 

最后再来看一下缓存服务。缓存服务和我们的 MySQL 一样,我们既可以拿来用它做一些 ORTP 相关的一些事务型的一个内容,也可以将它去单纯地做一些商品或者对应的交易服务这个缓存。

 

因此我们缓存服务其实是和 MySQL 一样,也是适用于单点部署的一个状态。

 

接下来我们来看一下整套这样的一个架构是否有可以优化的一个空间。我们整个的 H5 的一个流量入口,通过 CDN 代理代理到了不同的公网的域名内,然后进行多机房灾备的一个隔离。

 

在整套的一个服务体系里边,服务之间是通过 HTTP 的流量入口去做流量的一个管理。同时我们互联网的服务应用是处于无状态式的一个管理模式。

 

最后在数据层面,对事物要求不是很高的一个读取操作,会做 ElasticSearch 集群的一个部署,对事物要求比较高或者对缓存有延迟依赖的一个服务,也会将缓存和数据库当作同样的一个数据源去做单机房的部署架构。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3