Https加密过程、与三次握手
三次握手是传输层的概念,HTTPS通常是 SSL + HTTP 的简称,目前使用的 HTTP/HTTPS 协议是基于 TCP 协议之上的,因此也需要三次握手。要在 TCP 三次握手建立链接之后,才会进行 SSL 握手的过程(即身份认证和密钥协商的过程)
- HTTPS的SSL握手流程图
http四次挥手详解
四次挥手的状态
-
FIN_WAIT_1:这个状态和FIN_WAIT_2状态都在再等待对方的回复,但是这两种状态是有区别的,FIN_WAIT_1就是主动方在ESTABLISHED状态的时候,想要主动关闭连接,向对方发送FIN报文,这时候就进入了FIN_WAIT_1状态。当他收到对方回复的ACK报文后,就进入了FIN_WAIT_2状态。 但是在实际操作中是很难遇到FIN_WAIT_1状态的,因为无论对方是什么情况都应该立刻回应ACK报文,但是FIN_WAIT_2状态还是可以在主动方中用netstat看到的。
-
FIN_WAIT_2:上面已经对FIN_WAIT_2讲解过了,当主动方进入FIN_WAIT_2时,就表示着半连接状态,也就是主动方还有数据要发给对方,这个数据就是之后的ACK,所有他要等一会儿才关闭连接。
-
CLOSE_WAIT:这个状态从表面也可以看出它的作用,就是等待关闭。当被动方接收到FIN时,会立刻回复一个ACK给对方,接下来就是进入CLOSE_WAIT状态。在这个状态中,被动方需要考虑自己还有没有数据要发送给对方,如果有可以继续发送,如果没有了就可以关闭连接了,发送一个FIN给对方。 这个状态其实也就是给自己一个缓冲的时间,让自己处理完需要处理的事,然后去关闭连接。
-
TIME_WAIT:这个状态就是一段时间后进行一些操作。当主动方收到了对方发来的FIN报文,并发出ACK报文,接下来就等
2MSL就可以进入CLOSED状态
了。其实,如果主动方在FIN_WAIT_1状态下,收到了对方的FIN+ACK标志的报文,就可以跳过FIN_WAIT_2状态直接进入TIME_WAIT状态了。 -
LAST_ACK:这个状态从表面不难不理解他的意思,这个状态就是被动方发送了FIN报文后,最后等待对方的ACK报文,收到ACK报文后就可以进入CLOSED状态了。
-
CLOSED:上面提到了几次这个状态,相比也猜出来了,这个状态表示的就是连接中断,已经关闭。
在上面的TIME_WAIT状态中有提到过2MSL,那么什么是2MSL呢?那么来详细说一下TIME_WAIT状态和里面的2MSL。
为什么需要TIME_WAIT?
TIME_WAIT在四次挥手中有着不可替代的位置,如果没有TIME-WAIT,主动方就会直接进入CLOSED状态,(假设主动方时客户端,被动方时服务端)这时候如果立即重启客户端使用相同的端口,如果因为网络中种种原因最后一次ACK丢失了,服务端就会重复FIN请求,这时这个FIN就会被重新启动的客户端接收到,或者新启动的客户端向服务端发起请求的时候,因为服务端正在等待最后一次ACK,因此新连接请求发送的SYN就会被服务端认为时请求码错误,服务端就会回复RET重置连接。所以就需要主动方发送最后一次ACK之后进入TIME_WAIT状态,等待2MSL(两个报文最大生命周期),等待这段时间就是为了如果接收到了重发的FIN请求能够进行最后一次ACK回复,让在网络中延迟的FIN/ACK数据都消失在网络中,不会对后续连接造成影响
那么为什么TIME_WAIT的时间是2MSL呢?
MSL是TCP报文的最大生命周期,因为TIME_WAIT持续在2MSL就可以保证在两个传输方向上的尚未接收到或者迟到的报文段已经消失,否则服务器立即重启,可能会收到来自上一个进程迟到的数据,但是这种数据很可能是错误的,同时也是在理论上保证最后一个报文可靠到达,假设最后一个ACK丢失,那么服务器会再重发一个FIN,这是虽然客户端的进程不在了,但是TCP连接还在,仍然可以重发LAST_ACK。
TIME_WAIT状态造成的危害
在高并发短连接的TCP服务器上,当服务器处理完请求后主动请求关闭连接,这样服务器上会有大量的连接处于TIME_WAIT状态,服务器维护每一个连接需要一个socket,也就是每个连接会占用一个文件描述符,而文件描述符的使用是有上限的,如果持续高并发,会导致一些连接失败。
还有一种情况,假设假设假设,今天双十一,这是一台Tmall的服务器,因为一些原因,服务器进程挂掉了,退出了,由于是服务器主动关闭连接,因此会有TIME_WAIT状态存在,也就意味着服务器进程想立即重启,但是起不来,因为端口(可能是80)还被之前处于TIME_WAIT的连接占用着,如果TIME_WAIT状态维持60秒,60秒服务器都起不来,双十一,啧啧。
如何避免?
可设置套接字选项为SO_REUSEADDR,该选项的意思是,告诉操作系统,如果端口忙,但占用该端口TCP连接处于TIME_WAIT状态,并且套接字选项为SO_REUSEADDR,则该端口可被重用。如果TCP连接处于其他状态,依然返回端口被占用。该选项对服务程序重启非常有用。
TCP粘包问题及解决办法
链接如下this
flask相关面试题
flask上下文
在Flask中,对一个请求进行处理时,视图函数一般都会需要请求参数、配置等对象,当然不能对每个请求都传参一层层到视图函数(这显然很不优雅嘛),为此,设计出了上下文机制(比如像我们经常会调用的request就是上下文变量)
分为
- 请求上下文
request
session - 程序上下文
current_app
g
这四个是上下文变量具体的作用是什么?
request:封装客户端发送的请求报文数据
session:用于记住请求之间的数据,通过签名的cookie实现,常用来记住用户登录状态
current_app:指向处理请求的当前程序实例,比如获取配置,经常会用current_app.config
g:当前请求中的全局变量,因为程序上下文的生命周期是伴随请求上下文产生和销毁的,所以每次请求都会重设。一般我会在结合钩子函数在请求处理前使用
flask 蓝图
pass
redis是单线程还是多线程
Redis的单线程,主要是指事件处理上(cpu计算上),但是Redis的其他功能,如持久化、异步删除这些都是由额外的线程执行的。在Redis6.0版本的多线程并非彻底的多线程,I/O线程只能同时执行读或者同时执行写操作。在开启多线程后,并不会存在线程并发的安全问题,因为Redis的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行。
Redis 6.0 之后为什么引入了多线程?
虽然 Redis 的主要工作(网络 I/O 和执行命令)一直是单线程模型,但是在 Redis 6.0 版本之后,也采用了多个 I/O 线程来处理网络请求,这是因为随着网络硬件的性能提升,Redis 的性能瓶颈有时会出现在网络 I/O 的处理上
所以为了提高网络 I/O 的并行度,Redis 6.0 对于网络 I/O 采用多线程来处理。但是对于命令的执行,Redis 仍然使用单线程来处理,所以大家不要误解 Redis 有多线程同时执行命令。
Redis 官方表示,Redis 6.0 版本引入的多线程 I/O 特性对性能提升至少是一倍以上
详解参考如下
http常见状态码
-
200
OK
请求成功。一般用于GET与POST请求 -
201
创建成功 -
301
永久性重定向。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替 -
302
临时性重定向。与301类似。但资源只是临时被移动。客户端应继续使用原有URI -
400
Bad Request
客户端请求报文中存在语法错误,服务器无法理解。浏览器会像200 OK一样对待该状态吗 -
401
Unauthorized
请求要求用户的身份认证,通过HTTP认证(BASIC认证,DIGEST认证)的认证信息,若之前已进行过一次请求,则表示用户认证失败 -
403
Forbidden
服务器理解请求客户端的请求,但是拒绝执行此请求 -
404
Not Found
服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面。也可以在服务器拒绝请求且不想说明理由时使用 -
429
请求次数超限制 -
500
Internal Server Error
服务器内部错误,无法完成请求,也可能是web应用存在bug或某些临时故障 -
503
Service Unavailable
由于超载或系统维护,服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中 -
504
Gateway Time-out
充当网关或代理的服务器,未及时从远端服务器获取请求
网络io模型,io多路复用,python异步编程底层实现
- python的异步编程底层是使用了操作系统的io多路复用机制和生成器实现的是吗
是的,Python的异步编程底层使用了操作系统提供的IO多路复用机制,并结合了生成器(generators)的概念来实现协程。
底层的IO多路复用机制(如select、epoll、IOCP等)允许程序同时监视多个文件描述符的状态,以确定哪些IO事件已经就绪,从而实现非阻塞的异步IO操作。
而生成器是Python中的一种特殊函数,它可以在函数执行过程中通过yield语句暂停执行,并在需要时恢复执行。生成器的这种特性被广泛应用于协程的实现。
在Python的协程中,生成器被用作异步任务的执行单元。协程函数使用async def关键字定义,并在函数体内通过yield语句暂停执行,将控制权交还给事件循环。当异步操作完成后,事件循环会通过生成器的send()方法将结果发送给协程,并恢复生成器的执行,使协程可以继续执行下去。
生成器的这种暂停和恢复执行的能力使得协程能够实现非阻塞的异步编程模型,以及在等待IO操作完成时能够切换到执行其他任务,提高程序的并发性能。
综上所述,Python的异步编程底层利用操作系统提供的IO多路复用机制来实现非阻塞的异步IO操作,而通过使用生成器来实现协程,使得异步任务可以暂停和恢复执行,从而实现高效的异步编程模型。
2.事件循环是如何知道哪个网络io的数据已经返回的
协程的事件循环一般是一个主线程,通过epoll的方式去监控网络io,是事件驱动+回调函数的通知方式,因此主线程不会被阻塞