当前位置: 首页 > news >正文

软件架构之前后端分离架构服务器端高并发演进之路

软件架构之前后端分离架构&服务器端高并发演进之路

  • 前后端分离架构
      • 从业务角度
      • 从质量属性
      • 从性能角度
  • 服务器端关于不同并发量的演进之路
    • 1. 单体架构
    • 2. 第一次演进:应用服务器和数据库服务器分开部署
    • 3. 第二次演进:引入本地缓存和分部署缓存
    • 4. 第三次演进:引入反向代理和负载均衡
    • 5. 第四次演进:数据库读写分离
    • 6. 第五次演进:[分库] 数据库按业务分库
    • 7. 第六次演进:[分表] 把大表拆分成小表
    • 8. 第七次演进:使多个Nginx负载均衡
    • 9. 第八次演进:通过DNS轮询实现机房之间的负载均衡
    • 10. 第九次演进:引入NoSQL数据库和搜索引擎等技术
    • 11. 第十次演进:大应用拆分为小应用
    • 12. 第十一次演进:复用的功能抽离成微服务
    • 13. 第十二次演进:引入企业服务总线ESB屏蔽服务接口的访问差异
    • 14. 第十三次演进:引入容器化技术实现运行环境隔离与动态服务管理
    • 15. 第十四次演进:以云平台承载系统

首先,当一个项目刚起步的时候,不能预知后续的访问量和并发能达到多少,在初步开发的架构选型中,采用前后端分离的架构。关于前后端分离架构,其优势如下:

前后端分离架构

前后端分离是一种软件系统架构模式,它将应用程序的前端和后端分离开发和部署。在这种架构中,前端和后端是独立的系统,通过API(应用程序接口)进行通信。

从业务角度

前后端分离架构可退可进,目前是一个应用刚起步的最基本架构。将前后端分离开来,则前端只需要负责跟人机进行交互,关注业务流程。后端则只需要关注算法数据,运算逻辑等。

从质量属性

前端关注易用性,美观;后端注重扩展性、可用性和性能。

从性能角度

前端消耗内存和带宽;后端有效消耗CPU。前后端消耗计算机硬件分工不同。前端考虑怎么跟人进行有效交互,后端则把重心放在怎么跟计算机打交道更高效稳定。

这样的前后端分离架构,使得在消耗计算机硬件如高性能、高可用方面能够有效剥离出来,只用一心一意的考虑把后端代码达到性能更优 下面介绍服务器端的性能优化演进之路。

服务器端关于不同并发量的演进之路

1. 单体架构

当一个项目在初期起始阶段,应用数量与用户数量都比较少,此时的应用服务器(如Tomcat)和数据库服务器部署在同一台服务器上,以淘宝为例:浏览器往www.taobao.com发起请求时,首先经果DNS服务器(域名解析系统)把域名转换成实际IP地址10.102.4.1,浏览器转而访问该IP对应的
Tomcat。
在这里插入图片描述
但是随着用户数量的增加,Tomcat和数据库之间竞争资源,单机性能不足以支撑业务。

2. 第一次演进:应用服务器和数据库服务器分开部署

Tomcat和数据库分别独占服务器资源,通过增加服务器分担应用的方式,显著的提高了两者各自的性能。
在这里插入图片描述
但是随着用户数量的增长,并发读写数据库成为了性能的瓶颈。

3. 第二次演进:引入本地缓存和分部署缓存

在Tomcat同服务器或者同JVM、中增加本地缓存,并在外部增加分布式缓存,缓存热点数据的HTML页面等。通过缓存能把绝大多数请求在读写数据库前拦截掉,大大降低数据库的压力。
在这里插入图片描述
缓存虽然抗住了大部分的访问请求,但是随着用户数量的增长,并发的压力还是主要落在了单机的Tomcat上,响应逐渐变慢。

4. 第三次演进:引入反向代理和负载均衡

在多台服务器上分别部署Tomcat,使用反向代理软件(Nginx)把请求均匀分发到每个Tomcat中。
在这里插入图片描述
虽然反向代理使用服务器可以支持的并发量大大增加,但是并发量的增加也意味着更多请求穿透到数据库,单机的数据库最终会成为性能瓶颈。

5. 第四次演进:数据库读写分离

把数据库划分为读库和写库,读库可以有多个,通过同步机制把写库的数据同步到读库,对于需要查询最新写入数据的场景,可以在缓存中多写一份,通过缓存获得最新数据。
在这里插入图片描述
但是随着业务逐渐变多,不同业务之间的访问量差距较大,不同业务直接竞争数据库资源,相互影响性能。

6. 第五次演进:[分库] 数据库按业务分库

把不同业务的数据保存到不同的数据库中,使业务之间的资源竞争降低。对于访问量大的业务,可以部署更多的服务器来支撑。
在这里插入图片描述
但是随着用户数量的增长,单机的写库会逐渐达到性能瓶颈。

7. 第六次演进:[分表] 把大表拆分成小表

比如针对评论数据,可以按照商品的ID进行Hash,路由到对应的表中存储;针对支付记录,可以按照支付的小时创建表,每个小时表继续拆分为小表,使用用户ID或记录编号来路由数据。只要实时操作的表数据量足够小,请求能够足够均匀地分发到多台服务器上的小表,那数据库就能通过水平扩展的方式来提升性能。
在这里插入图片描述
虽然数据库和Tomcat、都能够水平扩展,可以支撑的并发量大幅提升,但是随着用户量的增长,最终单机的Nginx会成为性能上的瓶颈。

8. 第七次演进:使多个Nginx负载均衡

由于性能瓶颈在Nginx,因此无法通过两层的Nginx来实现多个Nginx的负载均衡。LVS和F5是工作在网络第四层的负载均衡解决方案,其中LVS是软件,运行在操作系统内核态,可对TCP请求或更高层级的网络协议进行转发,因此支持的协议更丰富,并且性能也远高于Nginx,可假设单机的LVS可支持几十万个并发的请求转发;F5是一种负载均衡硬件,与LVS提供的能力类似,性能比LVS更高,但价格昂贵。由于LVS是单机版的软件,若LVS所在服务器宕机则会导致整个后端系统都无法访问,因此需要有备用节点。可使用keepalived软件模拟出虚拟IP,然后把虚拟IP绑定到多台LVS服务器上,浏览器访问虚拟IP时,会被路由器重定向到真实的LVS服务器,当主LVS服务器宕机时,keepalived软件会自动更新路由器中的路由表,把虚拟IP重定向到另外一台正常的LVS服务器,从而达到LVS服
务器高可用的效果。
在这里插入图片描述
由于LVS也是单机的,随着并发数量增长到几十万时,LVS服务器最终会达到性能瓶颈,此时用户数量达到千万甚至上亿级别,用户分布在不同的地区,与服务器机房距离不同,导致了访问的延迟会明显不同。

9. 第八次演进:通过DNS轮询实现机房之间的负载均衡

在DNS服务器中可配置一个域名对应多个IP地址,每个IP地址对应到不同的机房里的虚拟IP。当用户访问www.taobao.com时,DNS服务器会使用轮询策略或其他策略,来选择某个IP供用户访问。此方式能实现机房间的负载均衡,至此,系统可做到机房级别的水平扩展,千万级到亿级的并发量都可通过增加机房来解决,系统入口处的请求并发量不再是问题。
在这里插入图片描述
但是随着数据的丰富程度和业务的发展,检索、分析等需求越来越丰富,单单依靠数据库无法解决如此丰富的需求。

10. 第九次演进:引入NoSQL数据库和搜索引擎等技术

当数据库中的数据多到一定规模的时候,数据库就不适用于复杂查询了,往往只能满足普通查询的场景。对于统计报表的场景,在数据量大时不一定能跑出结果,而且在跑复杂查询时会导致其他查询变慢。
在这里插入图片描述
引入更多组件解决了丰富的需求,业务维度能够极大扩充,但随之而来的是一个应用包含了太多的业务代码,业务的升级迭代变得困难。

11. 第十次演进:大应用拆分为小应用

按照业务板块来划分应用代码,使单个应用的职责更清晰,相互之间可以做到独立升级迭代。
在这里插入图片描述
但是不同的应用之间可能存在共用的模块,由应用单独管理会导致相同的代码存在多份,导致公共功能在升级时全部应用代码要跟着升级。

12. 第十一次演进:复用的功能抽离成微服务

如用户管理、订单、支付、鉴权等功能在多个应用中都存在,那么可以把这些功能的代码单独抽取出来形成一个单独的服务来管理,这样的服务就是所谓的微服务,应用和服务之间通过HTTP、TCP或RPC请求等多种方式来访问公共服务,每个单独的服务都可以由单独的团队来管理。
在这里插入图片描述
但是由于不同服务的接口访问方式不同,应用代码需要适配多种访问方式才能使用服务。此外,应用访问服务,服务之间也可能互相访问,调用链将会变得非常复杂,逻辑变得混乱。

13. 第十二次演进:引入企业服务总线ESB屏蔽服务接口的访问差异

通过ESB统一进行访问协议转换,应用统一通过ESB来访问后端服务,服务与服务之间也通过ESB来互相调用,以此降低系统的耦合程度。这种单个应用拆分为多个应用,公共服务单独抽出来管理,并使用企业总线来解除服务之间耦合问题的架构,就是所谓的SOA(面向服务)架构。
在这里插入图片描述
但是随着业务不断发展,应用和服务都会不断变多,应用和服务的部署变得复杂,同一台服务器上部署多个服务还要解决运行环境冲突的问题。此外,对于如大促这类需要动态扩缩容的场景,需要水平扩展服务的场景,就需要在新增的服务器上准备运行环境,部署服务等,运维将变得十分困难。

14. 第十三次演进:引入容器化技术实现运行环境隔离与动态服务管理

目前最流行的容器化技术是Docker,最流行的容器管理服务是Kubernetes(K8S),应用/服务可以打包为Docker镜像,通过K8S来动态分发和部署镜像。Docker镜像可理解为一个能运行你的应用/服务的最小的操作系统,里面放着应用/服务的运行代码,运行环境根据实际的需要设置好。把整个“操作系统”打包为一个镜像后,就可以分发到需要部署相关服务的机器上,直接启动Docker镜像就可以把服务起起来,使服务的部署和运维变得简单。
在这里插入图片描述

15. 第十四次演进:以云平台承载系统

TODO

相关文章:

软件架构之前后端分离架构服务器端高并发演进之路

软件架构之前后端分离架构&服务器端高并发演进之路 前后端分离架构从业务角度从质量属性从性能角度 服务器端关于不同并发量的演进之路1. 单体架构2. 第一次演进:应用服务器和数据库服务器分开部署3. 第二次演进:引入本地缓存和分部署缓存4. 第三次演…...

第4节-PhotoShop基础课程-Ps格式

文章目录 前言1.像素认识2. 图层认识1.图层有上下前后遮挡关系2.橡皮檫可以擦掉选择图层的像素3.新建图层4.新建删除图层 3. 分辨率的理解4. 图片格式A 前言 本章主要介绍PS常用格式 1.像素认识 下面每个格子就是像素 2. 图层认识 1.图层有上下前后遮挡关系 2.橡皮檫可以擦…...

C语言malloc函数学习

malloc的全称是memory allocation,中文叫动态内存分配,用于申请一块连续的指定大小的内存块区域,以void*类型返回分配的内存区域地址; 函数原型为void *malloc(unsigned int size),在内存的动态存储区中分配一个长度为…...

从零开始学习deepsort目标追踪算法----原理和代码详解

目录 1.目标追踪的主要步骤 2、传统sort算法的流程 3.Deepsort算法流程 4、目标追踪整体代码 4.1 Configs文件目录下: 4.2 deep_sort/deep_sort/deep目录下: 4.3 deep_sort/deep_sort/sort目录下: 运行demo: DeepSORT&…...

第三章 LInux多线程开发 3.1-3.5线程创建 终止 分离

创建线程:(好好记住 可能会叫写代码) 一般情况下,main函数所在的线程我们称之为主线程(main线程),其余创建的线程称之为子线程。 程序中默认只有一个进程,fork()函数调用,2进行 程序…...

空间曲线的参数方程

空间曲线的参数方程 二维直线 经过一点 P ( x 0 , y 0 ) P(x_0,y_0) P(x0​,y0​)的方向向量为 n ( c o s θ , s i n θ ) n(cos\theta,sin\theta) n(cosθ,sinθ)的直线参数方程为: [ x y …...

非华为机型如何体验HarmonyOS鸿蒙系统 刷写HarmonyOS鸿蒙GSI系统以及一些初步的bug修复

最近很多视频网站有非华为机型使用HarmonyOS鸿蒙系统的演示。其实大都是刷了HarmonyOS鸿蒙系统gsi系统。体验还可以。有些刷入后bug较多。那么这些机型是如何刷写gsi?可以参考我以往帖子 安卓玩机搞机-----没有第三方包 刷写第三方各种GSI系统 体验非官方系统_gsi刷…...

Flutter 生成小程序的混合 App 实践

一、背景 微信小程序发展的越来越快,目前小程序甚至取代了大部分 App 的生态位,公司的坑位不增反降,只能让原生应用开发兼顾或换岗进行小程序的开发。 以我的实际情况来讲,公司应用采用的 Flutter 框架,同样的功能不可避免的就会存在 Flutter 应用开发和微信小程序开发兼…...

利用 Python-user-agents 解析 User_Agent

利用 Python-user-agents 解析 User_Agen 需求分析 近期在尝试做一个登录日志的功能,及用户登录成功后我在后台进行一个用户的登录记录,两种解决方案: 由前端得到用户的手机型号,我在后台接收后在数据库进行保存使用User_Agent…...

Java版企业电子招标采购系统源码Spring Cloud + Spring Boot +二次开发+ MybatisPlus + Redis

功能描述 1、门户管理:所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含:招标公告、非招标公告、系统通知、政策法规。 2、立项管理:企业用户可对需要采购的项目进行立项申请,并提交审批,查看…...

Mybatis如何给字段起别名?

Mybatis如何给字段起别名? 假如有一个学生表,有一个字段是class,你的实体类变量肯定不能用class,那么如何起别名? 通过以下代码实现 Result(column "class",property "clas")mapper代码 pub…...

php对接AWS S3云存储,上传S3及访问权限问题

首先先下载sdk包 https://docs.aws.amazon.com/zh_cn/sdk-for-php/v3/developer-guide/getting-started_installation.html S3创建存储桶 去安全凭证-》创建访问秘钥 创建的时候会提示,主账号创建不安全,这个时候我们需要创建一个IAM账号来创建秘钥 创…...

java 实现单例模式

单例模式是一种设计模式,用于确保一个类只有一个实例,并提供一种全局访问该实例的方式。在Java中,可以使用多种方式来实现单例模式,下面整理了几种常见的实现方式。 饿汉式单例模式(Eager Initialization)&…...

minio文件服务器开启https

一、准备证书 你要有https安全证书,我的是适用于nginx的证书 私钥 xxxx.key 公钥 xxxx.pem 二、上传证书到minio服务器 然后看看你的minio docker 有没有把 /root/.minio 挂载在主机上,如果有那么把两个证书文件放在/root/.minio/certs目录里面。…...

每日刷题(回溯法经典问题之子集)

食用指南:本文为作者刷题中认为有必要记录的题目 前置知识:回溯法经典问题之组合 ♈️今日夜电波:想着你—郭顶 1:09 ━━━━━━️💟──────── 4:15 …...

PostgreSQL在进行除法时要注意

背景 整型除以整型,正常情况下当然得到的应该也是整型。数据库也是这么干的。 但是在数据库应用中,通常业务的需求是得到NUMERIC,不能直接把小数干掉。 数据库的行为给用户带来了诸多不便,例如1除以2,如果是整型除法会…...

开开心心带你学习MySQL数据库之第五篇

😺欢迎来到我的博客, 记得点赞👍收藏⭐️留言✍️🐱 🐉做为一个怪兽,我的目标是少消灭一个奥特曼🐉 📖希望我写的博客对你有所帮助,如有不足,请指正📖 chatgpt 是否能够代替程序猿?…...

Geotools对geojson的解析

在 GeoTools 中&#xff0c;对 GeoJSON 的支持是通过一个插件来完成的&#xff0c;用户同样可以在 Maven 的 pom.xml 配置文件中添加下述的依赖。 <dependency><groupId>org.geotools</groupId><artifactId>gt-geojson</artifactId><version&…...

【博客701】shell实现保留网络现场:ping失败时执行mtr

shell实现保留网络现场&#xff1a;ping失败时执行mtr 场景 当我们网络出现抖动&#xff0c;到某个目的地ping不通时&#xff0c;我们想知道路径上哪里出现问题时可以在那时候执行mtr并保留下现场以供排查 实现&#xff1a;ping_and_mtr.sh #!/bin/bash# 定义要ping的IP地址列…...

放弃手写代码吧!用低代码你能生成各种源码

很多同学不知道为什么要用Low-code做开发&#xff0c;传统IT开发不行么&#xff1f;当然可以。 传统IT自研软件开发&#xff0c;通过编程去写代码&#xff0c;还有数据库、API、第三方基础架构等。这个方式很好&#xff0c;但不可避免的会带来开发周期长、难度大&#xff0c;技…...

linux之kylin系统nginx的安装

一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源&#xff08;HTML/CSS/图片等&#xff09;&#xff0c;响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址&#xff0c;提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

SQL Server 触发器调用存储过程实现发送 HTTP 请求

文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...

JDK 17 序列化是怎么回事

如何序列化&#xff1f;其实很简单&#xff0c;就是根据每个类型&#xff0c;用工厂类调用。逐个完成。 没什么漂亮的代码&#xff0c;只有有效、稳定的代码。 代码中调用toJson toJson 代码 mapper.writeValueAsString ObjectMapper DefaultSerializerProvider 一堆实…...

用递归算法解锁「子集」问题 —— LeetCode 78题解析

文章目录 一、题目介绍二、递归思路详解&#xff1a;从决策树开始理解三、解法一&#xff1a;二叉决策树 DFS四、解法二&#xff1a;组合式回溯写法&#xff08;推荐&#xff09;五、解法对比 递归算法是编程中一种非常强大且常见的思想&#xff0c;它能够优雅地解决很多复杂的…...