后端知识体系--一次完整的HTTP请求

这里讲的请求是后端DevOps可以控制的范围内,不包括DNS解析,层层的路由等等,一切都从请求到达我们自己架设的服务器开始。

1.与服务器建立连接

1.1 TCP连接的建立

客户端的请求到达服务器,首先就是建立TCP连接

  1. Client首先发送一个连接试探,ACK=0 表示确认号无效,SYN = 1 表示这是一个连接请求或连接接受报文,同时表示这个数据报不能携带数据,seq = x 表示Client自己的初始序号(seq = 0 就代表这是第0号包),这时候Client进入syn_sent状态,表示客户端等待服务器的回复
  2. Server监听到连接请求报文后,如同意建立连接,则向Client发送确认。TCP报文首部中的SYN 和 ACK都置1 ,ack = x + 1表示期望收到对方下一个报文段的第一个数据字节序号是x+1,同时表明x为止的所有数据都已正确收到(ack=1其实是ack=0+1,也就是期望客户端的第1个包),seq = y 表示Server 自己的初始序号(seq=0就代表这是服务器这边发出的第0号包)。这时服务器进入syn_rcvd,表示服务器已经收到Client的连接请求,等待client的确认。
  3. Client收到确认后还需再次发送确认,同时携带要发送给Server的数据。ACK 置1 表示确认号ack= y + 1 有效(代表期望收到服务器的第1个包),Client自己的序号seq= x + 1(表示这就是我的第1个包,相对于第0个包来说的),一旦收到Client的确认之后,这个TCP连接就进入Established状态,就可以发起http请求了。

1.2 常见TCP连接限制

1.2.1 修改用户进程可打开文件数限制

在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。可使用ulimit命令查看系统允许当前用户进程打开的文件数限制,windows上是256,linux是1024,这个博客的服务器是65535

1.2.2 修改网络内核对TCP连接的有关限制

在Linux上编写支持高并发TCP连接的客户端通讯处理程序时,有时会发现尽管已经解除了系统对用户同时打开文件数的限制,但仍会出现并发TCP连接数增加到一定数量时,再也无法成功建立新的TCP连接的现象。出现这种现在的原因有多种。

第一种原因可能是因为Linux网络内核对本地端口号范围有限制。此时,进一步分析为什么无法建立TCP连接,会发现问题出在connect()调用返回失败,查看系统错误提示消息是“Can’t assign requestedaddress”。同时,如果在此时用tcpdump工具监视网络,会发现根本没有TCP连接时客户端发SYN包的网络流量。这些情况说明问题在于本地Linux系统内核中有限制。

其实,问题的根本原因在于Linux内核的TCP/IP协议实现模块对系统中所有的客户端TCP连接对应的本地端口号的范围进行了限制(例如,内核限制本地端口号的范围为1024~32768之间)。当系统中某一时刻同时存在太多的TCP客户端连接时,由于每个TCP客户端连接都要占用一个唯一的本地端口号(此端口号在系统的本地端口号范围限制中),如果现有的TCP客户端连接已将所有的本地端口号占满,则此时就无法为新的TCP客户端连接分配一个本地端口号了,因此系统会在这种情况下在connect()调用中返回失败,并将错误提示消息设为“Can’t assignrequested address”。

2.发起HTTP请求

2.1 请求格式

例如这样的一个请求

Accept 就是告诉服务器端,我接受那些MIME类型

Accept-Encoding 这个看起来是接受那些压缩方式的文件

Accept-Lanague 告诉服务器能够发送哪些语言

Connection 告诉服务器支持keep-alive特性

Cookie 每次请求时都会携带上Cookie以方便服务器端识别是否是同一个客户端

Host 用来标识请求服务器上的那个虚拟主机,比如Nginx里面可以定义很多个虚拟主机

那这里就是用来标识要访问那个虚拟主机。

User-Agent 用户代理,一般情况是浏览器,也有其他类型,如:wget curl 搜索引擎的蜘蛛等

条件请求首部:

If-Modified-Since 是浏览器向服务器端询问某个资源文件如果自从什么时间修改过,那么重新发给我,这样就保证服务器端资源

文件更新时,浏览器再次去请求,而不是使用缓存中的文件

安全请求首部:

Authorization: 客户端提供给服务器的认证信息

2.2 keep-alive/persitent

每次HTTP请求都重新建立TCP连接的开销是很大的,于是就出现了keep-alive这个首部,它允许在一次TCP连接中发送/接收多个HTTP报文

然而,keep-alive是有弊端的。在HTTP1.0中,客户端发起请求是加上keep-alive首部,服务端响应时也加上keep-alive首部,那么这个请求就被认为是keep-alive的,直到其中一方主动断开为止。如果没有正确断开,这个资源就会一直被占用了。

哑代理问题:哑代理只是单纯的转发请求,并不能进行解析处理、维持持久连接等其他工作,而聪明的代理可以解析接收到的报文同时可以维持持久连接。

 如上图,当客户端与服务器之间存在不解析直接转发的代理时,connection:keep-alive这个首部是直接转发给服务器的,服务器接收了这个请求之后,就会向客户端发送带有connection:keep-alive的响应,同样盲代理不会解析响应,直接将全部响应转发回客户端。因为客户端收到了这个首部,就认为建立持久连接已经成功了,但是中间的”笨代理“,并不知道这些事情,笨代理只有一种行为模式:在转发请求和回送服务器响应请求之后就认为这次事务结束了,等待连接断开,而这时由于connection:keep-alive首部已经发送到服务器和客户端,双方都认为持久连接已经建立完成,这样就变成了两边认为持久连接OK而中间的哑代理等待连接断开的情况,这种情况下如果客户端再一次在这条连接上发送请求,请求就会在亚代理处停止,因为哑代理已经在等待连接关闭。这种状态会导致浏览器一直处于挂起状态,直到客户端或服务器之中一个连接超时,关闭连接为止,一段美好的牵手就这么没了(哑代理就是把内容原封不动的转发到代理)。

为了避免这种情况,现代的代理是不会转发connection:keep-alive这个首部的。

persistent

HTTP/1.1的持久连接默认是开启的,只有首部中包含connection:close,才会事务结束之后关闭连接。当然服务器和客户端仍可以随时关闭持久连接。

当发送了connection:close首部之后客户端就没有办法在那条连接上发送更多的请求了。当然根据持久连接的特性,一定要传输正确的content-length。

还有根据HTTP/1.1的特性,是不应该和HTTP/1.0客户端建立持久连接的。最后,一定要做好重发的准备。

管道化连接

HTTP/1.1允许在持久连接上使用管道,这样就不用等待前一个请求的响应,直接在管道上发送第二个请求,在高延迟下,提高性能。

管道化连接的限制:

  • 不是持久连接就不能使用管道。
  • 必须按照同样的发送顺序回送响应,因为报文没有标签,很可能就顺序就乱咯。
  • 因为可以随时关闭持久连接,所以要随时做好重发准备
  • 不应该使用管道化发送重复发送会有副作用的请求(如post,重复提交)。

3.负载均衡

接收到HTTP请求之后,就轮到负载均衡登场了,它位于网站的最前端,把短时间内较高的访问量分摊到不同机器上处理。负载均衡方案有软件、硬件两种

F5 BIG-IP是著名的硬件方案,但这里不作讨论

软件方案有LVS HAProxy Nginx等,留作以后补充

4.Nginx(WEB服务器)

在典型的Rails应用部署方案中,Nginx的作用有两个

  1. 处理静态文件请求
  2. 转发请求给后端的Rails应用

这是一个简单的Nginx配置文件

后端的Rails服务器通过unix socket与Nginx通信,Nginx伺服public文件夹里的静态文件给用户

5.Rails(应用服务器)

这篇文章无敌了,我没有更多可以写的,只能说一句我用的是Puma。因为服务器是单核的,只能用多线程Puma或者事件驱动的Thin,考虑到以后可能用上Rails 5 ActionCabel,还是直接上Puma吧。

6.数据库(数据库服务器)

应用服务器想访问数据库,就需要与数据库建立连接。Rails读取database.yml中的配置,访问对应的数据库。

一个重要的配置指标pool: Rails中的数据库连接是完全线程安全的,所有pool的值要配置成与Puma的最大线程数相等,这样就不会出现线程等待数据库连接的情况。

7.Redis、Memercache(缓存服务器)

8.消息队列

9.搜索

参考文献

一次完整的HTTP事务是怎样一个过程?

Linux下高并发socket最大连接数所受的各种限制

Keep-Alive

谈谈持久连接——HTTP权威指南读书心得(五)

数据库连接池的工作原理

时间: 2024-10-09 00:21:55

后端知识体系--一次完整的HTTP请求的相关文章

一个完整的HTTP请求过程详细

整个流程1.域名解析 —> 2.与服务器建立连接 —> 3.发起HTTP请求 —>4. 服务器响应HTTP请求,浏览器得到html代码 —> 5.浏览器解析html代码,并请求html代码中的资源(如js.css.图片) —> 6.浏览器对页面进行渲染呈现给用户 1. 域名解析 以Chrome浏览器为例: ① Chrome浏览器 会首先搜索浏览器自身的DNS缓存(缓存时间比较短,大概只有1分钟,且只能容纳1000条缓存),看自身的缓存中是否有https://www.cnblo

软件工程专业知识体系

一 软件工程专业知识体系 终究是要毕业走人了,简单回顾一下这三年半专业教育,都学了些什么. 二 专业素养/开发能力 自己专业能力上又会些什么.总体特点:开发能力全而广,但深度不够. 三 Java后端知识体系 Java后端面试经验合集 四 产品经理知识体系 产品经理面试经验合集 五 Web前端知识体系 Web前端面试经验合集 原文地址:https://www.cnblogs.com/johnnyzen/p/10201181.html

前端知识体系2

Raw Blame History 1226 lines (983 sloc) 67.4 KB QQ联盟群交流(492107297)群规 GITHUB在线地址 http://t.cn/RL2NtqX 看云在线地址 http://t.cn/RUdaGHn 这是我们联盟群的组织结构,加入等级参考JS高级前端开发群加群说明. 这本来是我QQ群内部的一份公共约定的日常交流规则,后来得到大伙的一致认可,并用实际行动来捍卫它,使我倍受感动. 后来想:传播使爱更有力量,阅读使内心更为坚强,沉淀使生活更为醇香,

一文读懂分布式架构知识体系(内含超全核心知识大图)

作者 | 晓土  阿里巴巴高级工程师 姊妹篇阅读推荐:<云原生时代,分布式系统设计必备知识图谱(内含22个知识点)> 导读:本文力求从分布式基础理论.架构设计模式.工程应用.部署运维.业界方案这几大方面,介绍基于 MSA(微服务架构)的分布式知识体系大纲,从而对 SOA 到 MSA 进化有着立体的认识:从概念上和工具应用上更近一步了解微服务分布式的本质,身临其境的感受如何搭建全套微服务架构的过程. 关注“阿里巴巴云原生”公众号,回复“分布”,即可下载分布式系统及其知识体系清晰大图! 随着移动互

[转帖]一文读懂分布式架构知识体系(内含超全核心知识大图)

一文读懂分布式架构知识体系(内含超全核心知识大图) https://yq.aliyun.com/articles/721007?spm=a2c4e.11153959.0.0.2f464977X7lSdH 作者 | 晓土  阿里巴巴高级工程师 姊妹篇阅读推荐:<云原生时代,分布式系统设计必备知识图谱(内含22个知识点)> 导读:本文力求从分布式基础理论.架构设计模式.工程应用.部署运维.业界方案这几大方面,介绍基于 MSA(微服务架构)的分布式知识体系大纲,从而对 SOA 到 MSA 进化有着立

认知,构建个人的知识体系(上)

1.前言 本文将聊聊我对构建个人知识体系的一些想法,主要是为了提升自我认知.从个人经历开始,谈谈对知识的划分,也就是一个是什么,为什么的过程. 2.缘起 把时间回到一年前,那时候我工作快一年了,得益于前面的一些努力,工作比较顺利.特别是技术上,没有遇到太多过无法解决的问题.同时也开始迷茫,工作难道就是这个轻松的样子?三五年之后那不是很无趣,该怎么办? 想找到这个问题的答案,而最好的方式莫过于,亲自去了解那些三五年工作经验的人是怎么的样子. 因此从那时候起,关注了不少来公司面试的人的简历,也有过几

如何搭建数据化运营知识体系

数据化运营的概念随着大数据时代的到来被炒得越来越火热,提到数据分析.数据运营让很多产品经理.运营新人觉得瞬间高大上很多.随着数据概念的火热,如增长黑客.GrowingIO等一系列的数据分析指导产品增长的书籍.产品变得越来越受人追捧. 对于互联网行业来说,无论是产品经理还是运营,都需要具备一定的数据运营能力,本文将帮助没有数据化思维的小伙伴搭建基础的数据化运营体系. 本文会按照上图中的数据化运营业务流程进行分析,从明确目标.数据指标制定.数据获取.数据分析.形成策略.验证优化这六个方面来搭建数据化

Web 前端知识体系精简

Web前端技术由html.css和javascript三大部分构成,是一个庞大而复杂的技术体系,其复杂程度不低于任何一门后端语言.而我们在学习它的时候往往是先从某一个点切入,然后不断地接触和学习新的知识点,因此对于初学者很难理清楚整个体系的脉络结构.本文将对Web前端知识体系进行简单的梳理,对应的每个知识点点到为止,不作详细介绍.目的是帮助大家审查自己的知识结构是否完善,如有遗漏或不正确的地方,希望共勉. JAVASCRIPT 篇 0.基础语法 Javascript基础语法包括:变量定义.数据类

前端涉及的所有知识体系

资源教程: 综合类 前端知识体系 前端知识结构 Web前端开发大系概览 Web前端开发大系概览-中文版 Web Front-end Stack v2.2 免费的编程中文书籍索引 前端书籍 前端免费书籍大全 前端知识体系 免费的编程中文书籍索引 智能社 - 精通JavaScript开发 重新介绍 JavaScript(JS 教程) 麻省理工学院公开课:计算机科学及编程导论 JavaScript中的this陷阱的最全收集--没有之一 JS函数式编程指南 JavaScript Promise迷你书(中