web服务器(1)

news/2024/4/19 21:26:52/文章来源:https://blog.csdn.net/Neo_21/article/details/129231773

阻塞和非阻塞、同步和异步

网络IO阶段一:数据就绪     

操作系统,tcp接受缓冲区  

阻塞:调用IO方法的线程进入阻塞状态

非阻塞:不会改变线程的状态,通过返回值判断

网络IO阶段二:数据读写

应用程序

同步:char buf[1024] = {0};

           int   size  =  recv(sockfd,buf,1024,0);

           if (size>0)

           { buf }

         从TCP缓冲区搬数据到buf中

异步:异步IO接口,

陈硕:在处理IO的时候,阻塞和非阻塞都是同步IO,只有使用了特殊的API才是异步IO.

Unix、Linux上的五种IO模型

  1. 阻塞blocking

    调用者调用了某个函数,等待这个函数返回,期间什么也不做,不停去检查这个函数有没有返回,必须等待这个函数返回才能进行下一步动作

  2. 非阻塞 no-blocking 

    非阻塞等待,每隔一段时间按就去检测IO事件是否就绪。没就绪就可以做其他事情。非阻塞IO执行系统调用总是立即返回,不管事件是否已经发生,若没有发生则返回-1,此时就可根据errno区分情况。

  3. IO复用 IO multipling

    LINUX用select/poll/epoll函数实现IO复用模型,这些函数也会是进程阻塞,但是和阻塞IO不同的是这些函数可以同时阻塞多个IO操作。而且可以同时实现对多个读操作.写操作的IO函数进行检测,直到有数据可读或可写时 ,才真正调用IO操作函数。

  4. 信号驱动

    安装一个信号处理函数,进程继续运行并不阻塞,当IO事件就绪,进程收到SIGIO信号,然后处理IO事件。

  5. 异步

Web服务器简介及HTTP协议 

Web服务器:主要功能是通过HTTP协议与客户端(通常是浏览器)进行通信,来接受,存储,处理来自客户端的请求,并对其做出HTTP响应,返回给客户端其请求的内容(文件网页等)或返回一个error信息。

通常用户用户使用web服务器与相应服务器进行通信,在浏览器中键入“域名”或“IP地址:端口号”。

  1.  浏览器将你的域名解析成相应的IP地址,或直接根据IP地址向对应的服务器发送一个HTTP请求。
  2. 这一过程首先要通过TCP协议的三次握手,建立与目标服务器的连接
  3. 然后HTTP协议生成针对目标web服务器的HTTP请求报文,通过TCP/IP等协议发送到目标服务器上。

HTTP协议: 

HTTP 是超文本传输协议,也就是HyperText Transfer Protocol。不仅仅可以传输文本

「超文本」,它就是超越了普通文本的文本,它是文字、图片、视频等的混合体,最关键有超链接,能从一个超文本跳转到另外一个超文本。

HTML 就是最常见的超文本了,它本身只是纯文字文件,但内部用很多标签定义了图片、视频等的链接,再经过浏览器的解释,呈现给我们的就是一个文字、有画面的网页了。

HTTP 协议是一个双向协议

数据虽然是在 A 和 B 之间传输,但允许中间有中转或接力

HTTP 是一个在计算机世界里专门用来在两点之间传输数据的约定和规范。

HTTP 常见的状态码有哪些?

1xx 类状态码属于提示信息,是协议处理中的一种中间状态,实际用到的比较少。

2xx 类状态码表示服务器成功处理了客户端的请求,也是我们最愿意看到的状态。

  • 200 OK」是最常见的成功状态码,表示一切正常。如果是非 HEAD 请求,服务器返回的响应头都会有 body 数据。

  • 204 No Content」也是常见的成功状态码,与 200 OK 基本相同,但响应头没有 body 数据。

  • 206 Partial Content」是应用于 HTTP 分块下载或断点续传,表示响应返回的 body 数据并不是资源的全部,而是其中的一部分,也是服务器处理成功的状态。

3xx 类状态码表示客户端请求的资源发生了变动,需要客户端用新的 URL 重新发送请求获取资源,也就是重定向

  • 301 Moved Permanently」表示永久重定向,说明请求的资源已经不存在了,需改用新的 URL 再次访问。

  • 302 Found」表示临时重定向,说明请求的资源还在,但暂时需要用另一个 URL 来访问。

301 和 302 都会在响应头里使用字段 Location,指明后续要跳转的 URL,浏览器会自动重定向新的 URL。

  • 304 Not Modified」不具有跳转的含义,表示资源未修改,重定向已存在的缓冲文件,也称缓存重定向,也就是告诉客户端可以继续使用缓存资源,用于缓存控制。

4xx 类状态码表示客户端发送的报文有误,服务器无法处理,也就是错误码的含义。

  • 400 Bad Request」表示客户端请求的报文有错误,但只是个笼统的错误。

  • 403 Forbidden」表示服务器禁止访问资源,并不是客户端的请求出错。

  • 404 Not Found」表示请求的资源在服务器上不存在或未找到,所以无法提供给客户端。

5xx 类状态码表示客户端请求报文正确,但是服务器处理时内部发生了错误,属于服务器端的错误码。

  • 500 Internal Server Error」与 400 类型,是个笼统通用的错误码,服务器发生了什么错误,我们并不知道。

  • 501 Not Implemented」表示客户端请求的功能还不支持,类似“即将开业,敬请期待”的意思。

  • 502 Bad Gateway」通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误。

  • 503 Service Unavailable」表示服务器当前很忙,暂时无法响应客户端,类似“网络服务正忙,请稍后重试”的意思。

HTTP 常见字段有哪些?

Host 字段

客户端发送请求时,用来指定服务器的域名。

Host: www.A.com

 有了 Host 字段,就可以将请求发往「同一台」服务器上的不同网站。

Content-Length 字段

服务器在返回数据时,会有 Content-Length 字段,表明本次回应的数据长度。

Content-Length: 1000

如上面则是告诉浏览器,本次服务器回应的数据长度是 1000 个字节,后面的字节就属于下一个回应了。

Connection 字段

Connection 字段最常用于客户端要求服务器使用「HTTP 长连接」机制,以便其他请求复用。

Connection: Keep-Alive

Content-Type 字段

Content-Type 字段用于服务器回应时,告诉客户端,本次数据是什么格式。

Content-Type: text/html; Charset=utf-8

上面的类型表明,发送的是网页,而且编码是UTF-8。

Content-Encoding 字段

说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式

Content-Encoding: gzip

上面表示服务器返回的数据采用了 gzip 方式压缩,告知客户端需要用此方式解压。

客户端在请求时,用 Accept-Encoding 字段说明自己可以接受哪些压缩方法。

 服务器编程基本框架:

虽然服务器种类繁多,但其基本框架都一样,不同之处在于逻辑处理。

解析请求,做出响应

 事件处理模式

服务器通常需要处理三类事件:I/O事件,信号及定时事件。

有两种高效的事件处理模式,Reactor模式,Procator。

如果要让服务器服务多个客户端,那么最直接的方式就是为每一条连接创建线程。

        其实创建进程也是可以的,原理是一样的,进程和线程的区别在于线程比较轻量级些,线程的创建和线程间切换的成本要小些,为了描述简述,后面都以线程为例。

        处理完业务逻辑后,随着连接关闭后线程也同样要销毁了,但是这样不停地创建和销毁线程,不仅会带来性能开销,也会造成浪费资源,而且如果要连接几万条连接,创建几万个线程去应对也是不现实的。

        要这么解决这个问题呢?我们可以使用「资源复用」的方式。也就是不用再为每个连接创建线程,而是创建一个「线程池」,将连接分配给线程,然后一个线程可以处理多个连接的业务。

线程怎样才能高效地处理多个连接的业务?

        当一个连接对应一个线程时,线程一般采用「read -> 业务处理 -> send」的处理流程,如果当前连接没有数据可读,那么线程会阻塞在 read 操作上( socket 默认情况是阻塞 I/O),不过这种阻塞方式并不影响其他线程。

        但是引入了线程池,那么一个线程要处理多个连接的业务,线程在处理某个连接的 read 操作时,如果遇到没有数据可读,就会发生阻塞,那么线程就没办法继续处理其他连接的业务。要解决这一个问题,最简单的方式就是将 socket 改成非阻塞,然后线程不断地轮询调用 read 操作来判断是否有数据,这种方式虽然该能够解决阻塞的问题,但是解决的方式比较粗暴,因为轮询是要消耗 CPU 的而且随着一个 线程处理的连接越多,轮询的效率就会越低。

        上面的问题在于,线程并不知道当前连接是否有数据可读,从而需要每次通过 read 去试探。那有没有办法在只有当连接上有数据的时候,线程才去发起读请求呢?答案是有的,实现这一技术的就是 I/O 多路复用。

        I/O 多路复用技术会用一个系统调用函数来监听我们所有关心的连接,也就说可以在一个监控线程里面监控很多的连接。

我们熟悉的 select/poll/epoll 就是内核提供给用户态的多路复用系统调用,线程可以通过一个系统调用函数从内核中获取多个事件。

Reactor 模式

        Reactor 翻译过来的意思是「反应堆」,可能大家会联想到物理学里的核反应堆,实际上并不是的这个意思。这里的反应指的是「对事件反应」,也就是来了一个事件,Reactor 就有相对应的反应/响应。 

I/O 多路复用监听事件,收到事件后,根据事件类型分配(Dispatch)给某个进程 / 线程。

Reactor 模式主要由 Reactor 和处理资源池这两个核心部分组成,它俩负责的事情如下:

  • Reactor 负责监听和分发事件,事件类型包含连接事件、读写事件;
  • 处理资源池负责处理事件,如 read -> 业务逻辑 -> send;

Reactor 模式是灵活多变的,可以应对不同的业务场景,灵活在于:

  • Reactor 的数量可以只有一个,也可以有多个;
  • 处理资源池可以是单个进程 / 线程,也可以是多个进程 /线程;

方案具体使用进程还是线程,要看使用的编程语言以及平台有关:

  • Java 语言一般使用线程,比如 Netty;
  • C 语言使用进程和线程都可以,例如 Nginx 使用的是进程,Memcache 使用的是线程。

单 Reactor 多线程 / 多进程

如果要克服「单 Reactor 单线程 / 进程」方案的缺点,那么就需要引入多线程 / 多进程,这样就产生了单 Reactor 多线程 / 多进程的方案。

闻其名不如看其图,先来看看「单 Reactor 多线程」方案的示意图如下:

 

详细说一下这个方案:

  • Reactor 对象通过 select (IO 多路复用接口) 监听事件,收到事件后通过 dispatch 进行分发,具体分发给 Acceptor 对象还是 Handler 对象,还要看收到的事件类型;
  • 如果是连接建立的事件,则交由 Acceptor 对象进行处理,Acceptor 对象会通过 accept 方法 获取连接,并创建一个 Handler 对象来处理后续的响应事件;
  • 如果不是连接建立事件, 则交由当前连接对应的 Handler 对象来进行响应;

上面的三个步骤和单 Reactor 单线程方案是一样的,接下来的步骤就开始不一样了:

  • Handler 对象不再负责业务处理,只负责数据的接收和发送,Handler 对象通过 read 读取到数据后,会将数据发给子线程里的 Processor 对象进行业务处理;
  • 子线程里的 Processor 对象就进行业务处理,处理完后,将结果发给主线程中的 Handler 对象,接着由 Handler 通过 send 方法将响应结果发送给 client;

单 Reator 多线程的方案优势在于能够充分利用多核 CPU 的能,那既然引入多线程,那么自然就带来了多线程竞争资源的问题。

Proactor

前面提到的 Reactor 是非阻塞同步网络模式,而 Proactor 是异步网络模式

先来看看阻塞 I/O,当用户程序执行 read ,线程会被阻塞,一直等到内核数据准备好,并把数据从内核缓冲区拷贝到应用程序的缓冲区中,当拷贝过程完成,read 才会返回。

注意阻塞等待的是「内核数据准备好」和「数据从内核态拷贝到用户态」这两个过程

         知道了阻塞 I/O ,来看看非阻塞 I/O,非阻塞的 read 请求在数据未准备好的情况下立即返回,可以继续往下执行,此时应用程序不断轮询内核,直到数据准备好,内核将数据拷贝到应用程序缓冲区,read 调用才可以获取到结果。过程如下图:

 因此,无论 read 和 send 是阻塞 I/O,还是非阻塞 I/O 都是同步调用。因为在 read 调用时,内核将数据从内核空间拷贝到用户空间的过程都是需要等待的,也就是说这个过程是同步的,如果内核实现的拷贝效率不高,read 调用就会在这个同步过程中等待比较长的时间

异步IO

而真正的异步 I/O 是「内核数据准备好」和「数据从内核态拷贝到用户态」这两个过程都不用等待

当我们发起 aio_read (异步 I/O) 之后,就立即返回,内核自动将数据从内核空间拷贝到用户空间,这个拷贝过程同样是异步的,内核自动完成的,和前面的同步操作不一样,应用程序并不需要主动发起拷贝动作。过程如下图:

 

举个你去饭堂吃饭的例子,你好比应用程序,饭堂好比操作系统。

        阻塞 I/O 好比,你去饭堂吃饭,但是饭堂的菜还没做好,然后你就一直在那里等啊等,等了好长一段时间终于等到饭堂阿姨把菜端了出来(数据准备的过程),但是你还得继续等阿姨把菜(内核空间)打到你的饭盒里(用户空间),经历完这两个过程,你才可以离开。

        非阻塞 I/O 好比,你去了饭堂,问阿姨菜做好了没有,阿姨告诉你没,你就离开了,过几十分钟,你又来饭堂问阿姨,阿姨说做好了,于是阿姨帮你把菜打到你的饭盒里,这个过程你是得等待的。

        异步 I/O 好比,你让饭堂阿姨将菜做好并把菜打到饭盒里后,把饭盒送到你面前,整个过程你都不需要任何等待。

        很明显,异步 I/O 比同步 I/O 性能更好,因为异步 I/O 在「内核数据准备好」和「数据从内核空间拷贝到用户空间」这两个过程都不用等待。

Proactor 正是采用了异步 I/O 技术,所以被称为异步网络模型。

Proactor 模式的示意图:

介绍一下 Proactor 模式的工作流程:

  • Proactor Initiator 负责创建 Proactor 和 Handler 对象,并将 Proactor 和 Handler 都通过 Asynchronous Operation Processor 注册到内核;
  • Asynchronous Operation Processor 负责处理注册请求,并处理 I/O 操作;
  • Asynchronous Operation Processor 完成 I/O 操作后通知 Proactor;
  • Proactor 根据不同的事件类型回调不同的 Handler 进行业务处理;
  • Handler 完成业务处理;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_74824.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新闻稿的制作流程:从确定新闻稿目的到将其分发给媒体

对于任何希望向媒体和公众传达具有新闻价值的信息的组织来说,新闻稿都是必不可少的工具。精心制作的新闻稿可以帮助您宣传您的业务、产品或服务,并可以产生有价值的媒体报道。在本文中,我们将指导您完成新闻稿的制作过程,从确定新…

社区1月月报|OceanBase 4.1 即将发版,哪些功能将会更新?

我们每个月都会和大家展开一次社区进展的汇报沟通会,希望通过更多的互动交流让OceanBase 开源社区更加透明,实现信息共享,也希望能营造更加轻松的氛围,为大家答疑解惑,让大家畅所欲言。如果您对我们的社区有任何建议&a…

C#多窗口切换

多窗口切换【功能目标】1、实现多窗口切换(Panel)2、动态生成窗口内文本框以及标签(重点)3、改变文本框内容【效果图】【代码详解】1、多窗口切换如要实现多窗口切换,需要用到Panel,对于这个控件不熟悉的可…

13-mvc框架原理与实现方式

1、mvc原理 # mvc 与框架## 1.mvc 是什么1. m:model,模型(即数据来源),主要是针对数据库操作 2. v:view,视图,html 页面。视图由一个一个模板构成(模板是视图的一个具体展现或载体,视图是模板的一个抽象) 3. c:controller,控制器,用于mv之间的数据交互## 2.最简单的 mvc 就是一…

锁相环的组成和原理及应用

一.锁相环的基本组成 许多电子设备要正常工作,通常需要外部的输入信号与内部的振荡信号同步,利用锁相环路就可以实现这个目的。 锁相环路是一种反馈控制电路,简称锁相环(PLL)。锁相环的特点是:利用外部输入的参考信号控制环路内…

阶段八:服务框架高级(第五章:服务异步通信-高级篇(RabbitMQ高级))

阶段八:服务框架高级(第五章:服务异步通信-高级篇(RabbitMQ高级))Day-第五章:服务异步通信-高级篇(RabbitMQ高级)0.学习目标1.消息可靠性1.1.生产者消息确认1.1.1.修改配…

400G光模块知识大全

400G光模块是目前高速传输领域中的一种先进产品,被广泛应用于高性能数据中心、通信网络、大规模计算、云计算等领域。本文将从400G光模块的定义、技术、产品型号、应用场景以及未来发展方向进行详细介绍。一、什么是400G光模块?400G光模块是指传输速率达…

Android zygote进程启动流程

zygote启动过程中涉及到以下模块: app_processzygote USAPsocketFileDescriptor (FD) AndroidRuntimeAppRuntime (定义于app_process模块,继承自AndroidRuntime。) init进程启动zygote进程: #init.zygote32_64.rc s…

前端开发_快应用开发

目录快应用官网真机调试组件组件嵌套问题tab组件list组件web组件css 样式问题[1]选择器[2]盒模型[3]样式布局-弹性布局[4-1]样式切换 - 类名的动态切换[4-2] 样式切换 - 行内样式动态切换[5]background[6]overflow[7]border-radius[8]盒子阴影[9] 单位系统接口[1] 检查某app是否…

redis五种数据结构

redis五种数据结构1. redis 其他相关1.1 redis 的安装1.2 redis 的持久化1.3 redis 配置文件2. redis 常见命令2.1 key2.2 设置 key 的生存时间或过期时间3. redis的5种常见的数据结构3.1 String3.2 list3.3 hash3.4 set3.5 zset(SortedSet(有序集合&…

2023年“网络安全”赛项浙江省金华市选拔赛 任务书

2023年“网络安全”赛项浙江省金华市选拔赛 任务书 任务书 一、竞赛时间 共计3小时。 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段单兵模式系统渗透测试 任务一 Windows操作系统渗透测试 任务二 Linux操作系统渗透测试 任务三 网页渗透 任务四 Linux系统…

《爆肝整理》保姆级系列教程python接口自动化(二十四)--unittest断言——中(详解)

简介 上一篇通过简单的案例给小伙伴们介绍了一下unittest断言,这篇我们将通过结合和围绕实际的工作来进行unittest的断言。这里以获取城市天气预报的接口为例,设计了 2 个用例,一个是查询北京的天气,一个是查询 南京为例&#xf…

继电器的工作原理、构成和功能介绍

随着电力应用的不断发展,电气设备已经深入到我们的日常生活中,电气自动化技术大量使用在电力系统和生产型企业中,人们在享受电带来方便的同时要注意用电保护。继电器就是为了保护电路而生的,可以提高电路可靠性,保障用…

RabbitMQ实现死信队列

目录死信队列是什么怎样实现一个死信队列说明实现过程导入依赖添加配置编写mq配置类添加业务队列的消费者添加死信队列的消费者添加消息发送者添加消息测试类测试死信队列的应用场景总结死信队列是什么 “死信”是RabbitMQ中的一种消息机制,当你在消费消息时&#…

wafw00f 防火墙探测

kali机器自带防火墙探测工具wafw00,它可以通过发送正常以及不正常甚至包含恶意代码的HTTP请求,来探测网站是否存在防火墙,并识别防火墙的厂商及类型。安装:git clone https://github.com/EnableSecurity/wafw00f.git python setup…

Windows如何查看某个端口被占用的情况?

在工作中,有时会发现端口被占用的情况,导致软件报错或者服务无法启动等问题。在不知道具体哪个进程占用该端口号的情况下,我们可以用下面方法来查找。 举例:我现在发现8090端口被占用了,我现在需要找到并杀掉该进程。…

TCP状态转换

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 TCP状态转换专栏:《Linux从小白到大神》《网络编程》 TCP状态转换示意图如下 针对上面的示…

高并发之读多写少的场景设计(用户中心)

用户中心是一个典型的读多写少系统,可以说我们大部分的系统都属于这种类型,而这类系统通过缓存就能获得很好的性能提升。并且在流量增大后,用户中心通常是系统改造中第一个要优化的模块,因为它常常和多个系统重度耦合,…

消息队列介绍和RabbitMQ的安装

1.消息队列 1.1 MQ的相关概念 1.1.1 什么是MQ MQ(message queue),从字面意思上看,本质是个队列,FIFO 先入先出,只不过队列中存放的内容是message 而已,还是一种跨进程的通信机制,用于上下游传递消息。在…

高阶人生从在职读研开始——中国社科院与美国杜兰大学金融管理硕士

说到学历,好多人都不太在意,感觉学历没什么用。等升职学历被卡时,等你想考公学历达不到时,当你想跳槽更大的平台时,学历会显得尤其重要。当机会来临时,我们应该做好全足的准备,而不是眼瞅着机会…