[透彻]为什么要前后端分离?

2023-11-19

前后端分离的意义

前后端分离,已成为互联网项目开发的业界标准使用方式

前后端分离,会为以后的大型分布式架构、弹性计算架构、微服务架构打下坚实的基础。

核心思想: 前端页面调用后端的restuful api接口,并使用json数据进行交互。

服务器种类

  • web服务器

例如 nginx,apache这类服务器,一般只能解析静态资源

  • 应用服务器

例如 tomcat,jetty,resin这类服务器,可以解析动态资源,也可以解析静态资源,但解析静态资源的速度没有web服务器高效

一般而言,只有web服务器才能被外网访问,而应用服务器只能通过内网访问

以前的开发模式

早期的JavaWeb项目并不复杂,业务场景和逻辑都很简单,开发比较便捷。

因此,大多数都是java程序员又当爹又当妈,既搞前端(html/css/javascript/jsp),又搞后端(java/MySQL/ORM框架/接口开发)。

随着时代发展,很多公司的规模越来越大,业务场景也越来越复杂,前后端的界限也越来越明确。

前端工程师只负责前端,后端工程师只负责后端。

正所谓术业有专攻如果一个人什么都会,那他就不可能什么都精通

职业划分

  • 后端java工程师

java基础,设计模式,SpringBoot,Linux,MySQL数据库,ORM框架,多线程,弹性计算架构,微服务架构(Spring Cloud),jvm性能优化,以及相关的项目管理等。

后端追求的是:三高(高并发,高可用,高性能),安全,存储,业务等。

  • 前端工程师

html5,css3,javascipt,bootstrap,react,vue,webpack,gulp,node,多线程,模块化,面向切面编程,设计模式,浏览器兼容性,性能优化等。

前端追求的是:页面表现,速度流畅,兼容性,用户体验等。

项目解耦

几曾何时,我们的JavaWeb项目使用若干后台框架,Springmvc + Spring + Mybatis

java分层:控制层(controller),业务层(service),持久层(dao)

C层负责接收参数,调用相关业务层,封装数据,以及将数据渲染到Jsp页面

Jsp页面使用各种标签(Jstl/EL表达式/Struts标签)或者手写java表达式(<%=%>)将后台数据展现出来

项目如何发布?

将代码打成war包,然后把war包发布到web容器中(通常是Tomcat),进行启动。

然后通过配置域名,dns等等相关,网站就可以访问了

早期的开发模式,是把前后端代码放在一个地方,也就是war包。

问题:在浏览器中输入网站域名(www.xxx.com),发生了什么?

浏览器通过dns服务器,找到服务器ip,将http请求发送到服务器,在TCP3次握手之后,通过TCP协议开始传输数据,服务器得到请求后,开始提供服务,接收参数,之后响应数据到浏览器,浏览器解析数据,将其呈现给用户。

假设服务器首页中有100张图片,此时,用户点击首页,看似是一次HTTP请求。

其实并不是一次,用户在第一次访问的时候,浏览器中不会有缓存,你的100张图片,浏览器要连着请求100次HTTP请求

你的服务器接收这些请求,都需要耗费内存去创建socket来玩tcp传输(消耗服务器上的计算资源)。

重点来了,这样的话,服务器的压力会非常大。

因为页面中的所有请求都是只请求到你这台服务器上

如果1个人还好,如果10000个人并发访问呢(先不聊服务器集群,这里就说是单实例服务器)

服务器能扛住多少个TCP连接?

带宽有多大?

服务器的内存有多大?

硬盘是高性能的吗?

能抗住多少IO?

web服务器分配的内存有多大?

会不会宕机

因此,越是大中型的web应用,越要解耦

理论上,可以把数据库+应用服务+消息队列+缓存+用户上传的文件+日志等都扔在一台服务器上

你也不用玩什么服务治理,也不用做什么性能监控,什么报警机制等等,就乱成一锅粥好了。

但是这样,就好像把鸡蛋都放在一个篮子里,隐患非常大。

如果因为一个子应用的内存不稳定导致整个服务器内存溢出,那整个网站就挂了。

如果出意外挂掉,而恰好这时公司的业务处于井喷式,发展高峰期

那么恭喜你,业务成功被技术卡住,很可能会流失大量用户,后果不堪设想。

注意:技术一定要走在业务前面,否则将错过最佳的发展期

应用全部耦合在一起,相当于一个巨石

当服务端负载能力不足时,一般会使用负载均衡的方式,将服务器做成集群

这样,其实是在水平扩展一块块巨石,性能加速度会越来越低

要知道,本身负载就低的功能,完全没必要水平扩展的

本文的例子,你的性能瓶颈不在前端,何必水平扩展前端呢

还有

部署上线的时候,我明明只改了后端的代码,为什么要前端也跟着一起发布?

正常的互联网架构,是要拆开的

web服务器集群,应用服务器集群+文件服务器集群+数据库服务器集群+消息队列集群+缓存集群等。

JSP的痛点

以前的javaWeb项目,大多数使用JSP作为页面层,展示数据给用户

因为流量不高,也没有苛刻的性能要求

但现在是大数据时代,对于互联网项目的性能要求是越来越高

因此原始的前后端耦合在一起的架构模式,已经无法满足业务发展

因此我们需要寻找一种解耦方式,来大幅度提升我们的负载能力。

1.动态资源和静态资源全部耦合在一起,服务器压力大,因为服务器会收到各种HTTP请求,例如css的HTTP请求,js的,图片的等等。

一旦服务器出现状况,前后台一起玩完,用户体验极差。

2.UI出好设计图后,前端工程师只负责将设计图切成html,需要由java工程师来将html套成JSP页面,出错率较高(因为页面中经常会出现大量的js代码)

修改问题时需要双方协同开发,效率低下。

3.JSP必须要在支持java的web服务器里运行(例如tomcat,jetty,resin等),无法使用nginx等(nginx据说单实例HTTP并发高达5w,这个优势要用上)

性能提不上来

4.第一次请求jsp,必须要在web服务器中编译成servlet,第一次运行会较慢。

5.每次请求JSP都是访问servlet再用输出流输出的html页面,效率没有直接使用html高(是每次!)。

6.JSP内有较多标签和表达式,前端工程师在修改页面时会捉襟见肘,遇到很多痛点。

7.如果JSP中的内容很多,页面响应会很慢,因为是同步加载。

8.需要前端工程师使用java的ide(例如eclipse),以及需要配置各种后端的开发环境,你们有考虑过前端工程师的感受吗

基于上述的一些痛点,我们应该把整个项目的开发权重往前移,实现前后端真正的解耦!

开发模式

  • 旧的开发模式
1.产品经历/领导/客户提出需求
2.UI做出设计图
3.前端工程师做html页面
4.后端工程师将html页面套成jsp页面( 前后端强依赖,后端必须要等前端的html做好才能套jsp。开发效率低)
5.集成出现问题
6.前端返工
7.后端返工
8.二次集成
9.集成成功
10.交付
  • 新的开发模式
1.产品经历/领导/客户提出需求
2.UI做出设计图
3.前后端约定接口&数据&参数
4.前后端并行开发( 如果需求变更,只要接口&参数不变,就不用两边都修改代码,开发效率高)
5.前后端集成
6.前端页面调整
7.集成成功
8.交付

请求方式

  • 旧的请求方式
1.客户端请求
2.服务端的servlet或controller接收请求( 后端控制路由与渲染页面,整个项目开发的权重大部分在后端)
3.调用service,dao代码完成业务逻辑
4.返回jsp
5.jsp展现一些动态的代码
  • 新的请求方式:
1.浏览器发送请求
2.直接到达html页面( 前端 控制路由与渲染页面 ,整个项目开发的权重前移)
3.html页面负责调用服务端接口产生数据(通过ajax等等,后台返回json格式数据)
4.填充html,展现动态效果,在页面上进行解析并操作DOM。

总结一下,新方式的请求步骤:

大量并发浏览器请求—>web服务器集群(nginx)—>应用服务器集群(tomcat)—>文件/数据库/缓存/消息队列服务器集群

同时又可以玩分模块,还可以按业务拆成一个个的小集群,为后面的架构升级做准备。

前后分离的优势

  1. 前后端解耦,前端服务器放的是css,js,图片等一系列静态资源(甚至你还可以使用cdn加速),前端负责控制页面引用&跳转&路由,前端页面异步调用后端接口

  2. 发现bug,可以快速定位,不会出现互相踢皮球的现象,页面逻辑,跳转错误,浏览器兼容性问题,页面样式等问题,全部由前端工程师来负责。接口数据出错,数据没有提交成功,应答超时等问题,全部由后端工程师来解决。

  3. 大并发情况下,可以同时水平扩展前后端服务器,比如淘宝首页,需要2000+台前端服务器做集群来抗住数亿级别的日均pv。

  4. 减少后端服务器的并发/负载压力,理论上,除了接口以外的其他HTTP请求,应当全部转移到前端nginx上

  5. 即使后端服务暂时超时或者宕机了,前端页面也会正常访问,只不过数据刷不出来而已。

  6. 页面显示的东西再多也不怕,因为是异步加载。

  7. nginx支持热部署,不用重启服务器,前端升级更无缝。

  8. 增加代码的维护性和易读性

  9. 提升开发效率(并行开发)。

总结

  • 前后端分离并非仅仅只是一种开发模式,而是一种架构模式(前后端分离架构)。

  • 前后端工程师需要约定交互接口,实现并行开发,开发结束后需要进行独立部署

  • 前端只需要,关注页面样式与动态数据的解析&渲染,而后端专注于业务逻辑

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

[透彻]为什么要前后端分离? 的相关文章

  • 添加动态数量的监听器(Spring JMS)

    我需要添加多个侦听器 如中所述application properties文件 就像下面这样 InTopics Sample QUT4 Sample T05 Sample T01 Sample JT7 注意 这个数字可以多一些 也可以少一些
  • 如何在spring mvc中从控制器名称+操作名称获取映射的URL?

    是否有现有的解决方案可以从 Spring MVC3 中的 控制器名称 操作名称 获取映射的 URL 例如 asp net mvc 或 Rails 中的 UrlHelper 我觉得非常有用 thx 也许 你想要这样的东西 in your Co
  • 如何使用 SimpleDateFormat 解析多种格式的日期

    我正在尝试解析文档中的一些日期 用户似乎以类似但不完全相同的格式输入了这些日期 以下是格式 9 09 9 2009 09 2009 9 1 2009 9 1 2009 尝试解析所有这些内容的最佳方法是什么 这些似乎是最常见的 但我想让我困扰
  • Android 自定义视图不能以正确的方式处理透明度/alpha

    我正在绘制自定义视图 在此视图中 我使用两个不同的绘画和路径对象在画布上绘画 我基本上是在绘制两个重叠的形状 添加 Alpha 后 视图中重叠的部分比图像的其余部分更暗 这是不希望的 但我不知道如何解决它 这是我的代码片段 用于展示我如何在
  • 内存一致性 - Java 中的happens-before关系[重复]

    这个问题在这里已经有答案了 在阅读有关内存一致性错误的 Java 文档时 我发现与创建 发生 之前 关系的两个操作相关的点 当语句调用时Thread start 每个具有 与该语句发生之前的关系也有一个 与 new 执行的每个语句之间发生的
  • 如何让spring为JdbcMetadataStore创建相应的schema?

    我想使用此处描述的 jdbc 元数据存储 https docs spring io spring integration docs 5 2 0 BUILD SNAPSHOT reference html jdbc html jdbc met
  • 具有共享依赖项的多模块项目的 Gradle 配置

    使用 gradle 制作第一个项目 所以我研究了 spring gradle hibernate 项目如何组织 gradle 文件 并开始制作自己的项目 但是 找不到错误 为什么我的配置不起作用 子项目无法解决依赖关系 所以项目树 Root
  • Java 服务器-客户端 readLine() 方法

    我有一个客户端类和一个服务器类 如果客户端向服务器发送消息 服务器会将响应发送回客户端 然后客户端将打印它收到的所有消息 例如 如果客户端向服务器发送 A 则服务器将向客户端发送响应 1111 所以我在客户端类中使用 readLine 从服
  • Java 8 中函数式接口的使用

    这是来自的后续问题Java 8 中的 双冒号 运算符 https stackoverflow com questions 20001427 double colon operator in java 8其中 Java 允许您使用以下方式引用
  • Git 无法识别重命名和修改的包文件

    我有一个名为的java文件package old myfile java 我已经通过 git 提交了这个文件 然后我将我的包重命名为new所以我的文件在package new myfile java 我现在想将此文件重命名 和内容更改 提交
  • Java 数组的最大维数

    出于好奇 在 Java 中数组可以有多少维 爪哇language不限制维数 但是JavaVM规范将维度数限制为 255 例如 以下代码将无法编译 class Main public static void main String args
  • 无法加载或查找主类,可以在命令行中使用,但不能在 IDE 中使用[重复]

    这个问题在这里已经有答案了 在将其标记为重复之前 请先听我说完 我正在尝试使用 gradle 导入一个 java 项目 功能齐全 适用于所有其他笔记本电脑 没有问题 我的项目 100 正常运行 适用于所有其他笔记本电脑 当我的笔记本电脑被重
  • 如何将 Jfreechart(饼图)添加到 netbeans 的面板中

    我正在使用 netbeans gui 编辑器 并且正在尝试添加一个本身位于内部框架中的 Jfreechart 并且这个内部框架我想将其添加到面板中 正如您在此图中看到的那样 抱歉 我无法直接发布图像 因为我新手 http www flick
  • Java 收集返回顶级项目的映射的嵌套流

    我有以下模型 class Item String name List
  • 为什么java中的for-each循环中需要声明变量

    for 每个循环的通常形式是这样的 for Foo bar bars bar doThings 但如果我想保留 bar 直到循环结束 我可以not使用 foreach 循环 Foo bar null Syntax error on toke
  • 无法捕获 Spring Batch 的 ItemWriter 中的异常

    我正在编写一个 Spring Batch 流程来将数据集从一个系统迁移到另一个系统 在这种情况下 这就像使用RowMapper实现在传递给查询之前从查询构建对象ItemWriter The ItemWriter称为save我的 DAO 上的
  • 解决错误javax.mail.AuthenticationFailedException

    我不熟悉java中发送邮件的这个功能 我在发送电子邮件重置密码时遇到错误 希望你能给我一个解决方案 下面是我的代码 public synchronized static boolean sendMailAdvance String emai
  • JSTL 在循环中每 5 个字段集创建一个新行

    您好 我目前正在迭代并在表中显示字段集列表 为了让布局变得更得体一些 我想在每次循环到达第五个字段集时创建一个新行 谢谢 JSP div class det table class det tr td td tr table div
  • Java:拆箱整数时出现空指针异常?

    此代码导致空指针异常 我不知道为什么 private void setSiblings PhylogenyTree node Color color throws InvalidCellNumberException PhylogenyTr
  • Android AutoCompleteTextView 带芯片

    我不确定我是否使用了正确的词语来描述此 UI 功能 但我已附上我希望在我的应用程序中实现的目标的快照 它由 Go SMS 使用 用户在编辑文本中键入联系人 在用户从完成下拉列表中选择联系人后 该联系人将被插入到编辑文本中 如附图所示 编辑文

随机推荐

  • C语言—指针

    文章目录 1 指针 1 1 指针的定义 1 2 和 1 3 指针与堆内存 1 4 指针运算 1 5 常量指针与指针常量 1 5 1 常量指针 1 5 2 指针常量 1 6 函数指针 2 指针与数组 3 指针与函数 4 指针与链表 4 1 链
  • cmake中的编译选项

    CMake是一个跨平台的构建系统 它可以根据简单的配置文件生成各种平台的构建工具 例如Makefile Visual Studio项目文件等 CMake使用CMakeLists txt文件来描述项目的构建规则和依赖关系 在这个文件中 可以设
  • 浅谈opencv3.2中各个模块的简介

    3 2版本的模块说明 Opencv3 2模块 首先打开opencv modules hpp文件 可以看到对于各个功能模块的定义如下 This file defines the list of modules available in cur
  • 分享几个项目中用到的设计模式

    前言 之前项目中出于扩展性和有雅性的考虑 使用了多种设计模式进行项目框架的设计 主要的一些设计模式是单例模式 工厂模式 策略模式 责任链模式 代理模式这几种 现在依次讲讲这几个的主要是实现方式和在我们项目中的应用场景 核心设计模式分享 单例
  • WPF TextBlock 实现点击事件

    TextBlock 标签里定义MouseLeftButtonDown 事件 xaml cs
  • ICCV 2023

    ICCV 2023 MPI Flow 从单视角构建的多平面图像中学习光流 引言 主要贡献 Motivation 算法细节 Optical Flow Data Generation Independent Object Motions Dep
  • Node之使用dns模块解析域名

    引 在网络编程中 开发者更倾向于使用域名 而不是IP地址来指定网络连接的目标地址 在Node js中 提供dns模块 以实现域名查找及域名解析的处理 在dns模块中 提供了三个主方法及一系列便捷方法 其中三个主方法分别为用于将一个域名解析为
  • MySQL使用查询结果生成临时表

    MySQL中不支持对同一个表使用其查询结果更新or删除本表内数据 也就是update或delete后的where条件为针对相同表的select 解决方案是创建临时表做过度保存中间数据 可以直接使用查询结果来形成临时表 CREATE TABL
  • verilog奇数分频器的问题讲解(7分频为例)

    先不多哔哔 直接上代码 verilogHDL 代码的后面讲原理 module fenpin3 clk clk7 rst input clk rst 设置rst的目的是当rst 1的时候给cnt0和cnt1赋初值 output clk7 re
  • python sslerror_如何解决“不良握手”问题利用python请求时的SSLErrors

    I m trying to get access to the BambooHR API documentation here but I receive the following error params user username p
  • GREASELM: GRAPH REASONING ENHANCED LANGUAGE MODELS FOR QUESTION ANSWERING

    本文是LLM系列文章 针对 GREASELM GRAPH REASONING ENHANCED LANGUAGE MODELS FOR QUESTION ANSWERING 的翻译 GREASELM 图推理增强的问答语言模型 摘要 1 引言
  • 小霸王其乐无穷之函数回调

    小霸王游戏机是中国上一代备受欢迎的家用游戏机 它在1990年代初期开始流行 当时 由于游戏软件受限 国内的游戏市场相对匮乏 这使得小霸王游戏机成为许多70 80后童年时光中难忘的一部分 小霸王游戏机分为两大主要部分 游戏机本身和卡带 游戏机
  • Python中的CALL_FUNCTION指令

    在Python字节码中 CALL FUNCTION指令后跟的数字代表这次函数调用需要从栈上取出的参数的数量 具体来说 这个数字包括位置参数和关键字参数的数量 这个数字的低两位表示位置参数的数量 然后每两位表示一个关键字参数的数量 因此 如果
  • LLVM Language Reference Manual---阅读笔记

    文档地址 http llvm org docs LangRef html LLVM IR的标示符有两种基本类型 全局的和局部的 全局标示符以 开头 局部标示符以 开头 LLVM IR的标示符有三种形式 命名的 未命名的 常量 每一个Moud
  • Python pyecharts数据可视化

    Python pyecharts数据可视化 绘制精美图表 一 数据可视化 1 pyecharts介绍 2 初入了解 1 快速上手 2 简单的配置项介绍 3 案例实战 1 柱状图Bar 2 地图Map 省份 城市 地区 3 饼图Pie Pie
  • 【SMTP】【POP】电子邮件相关协议分析

    一 实验环境 通过普通路由器连接英特网的计算机一台 通过VMWare安装的Linux虚拟机一台 抓包工具 Wireshark 邮件处理软件 Foxmail 二 实验原理 SMTP工作原理 SMTP提供了一种邮件传输的机制 当收件方和发件方都
  • 公司实战 ElasticSearch+Kafka+Redis+MySQL

    一 需求 前一段时间公司要进行数据转移 将我们ES数据库中的数据转移到客户的服务器上 并且使用定时将新增的数据同步 在这过程中学到了很多 在此记录一下 二 技术栈 Mysql Redis ElasticSearch Kafka 三 方案 为
  • Ant Design Pro + Ant Design + React 踩坑记录

    1 自定义封装组件 1 1 组件通信 1 1 1 父传子 在本项目中对因为删除组件比较通用 所以对删除组件进行了封装 如下图我们对定义了通用删除组件 通过props传入回调方法 这样页面上只需要引用该组件 并传入自定义的删除函数即可引入 我
  • 单向链表实现(C语言)

    目录 一 简介 概念介绍 链接存储方法 结点结构 头指针head和终端结点 二 单向链表的使用 1 数据结构 2 从尾部添加append 3 从头部添加 add head 4 在链表任一指定位置节点按升序插入节点 5 查找并删除指定节点 6
  • [透彻]为什么要前后端分离?

    前后端分离的意义 前后端分离 已成为互联网项目开发的业界标准使用方式 前后端分离 会为以后的大型分布式架构 弹性计算架构 微服务架构打下坚实的基础 核心思想 前端页面调用后端的restuful api接口 并使用json数据进行交互 服务器