以下题目来自于牛客网的面经真题,希望能对大伙有帮助。
物数网传会表应
应用层:针对特定应用的协议,为应用程序提供服务并规定应用程序中通信相关的细节。包括文件传输、电子邮件、远程登录等协议。
表示层:将来自下一层的数据转换为上层能够处理的格式。负责数据转换、格式化、文本压缩等。
会话层:负责建立和断开通信连接(数据流动的逻辑通路),以及数据的分割等数据传输相关的管理。
传输层:管理两个节点之间的数据传输。
网络层:地址管理和路由选择。
数据链路层:互联设备之间传送和识别帧。
物理层:以二进制形式在在物理媒体上传输数据。
应用层常见协议:Http、Telnet、POP、DNS、FTP
传输层协议:TCP、UDP
TCP 面向连接(如打电话要先拨号建立连接)提供可靠的服务,UDP 是无连接的,即发送数据之前不需要建立连接,UDP 尽最大努力交付,即不保证可靠交付。
UDP 具有较好的实时性,工作效率比 TCP 高,适用于对高速传输和实时性有较高的通信或广播通信。
每一条 TCP 连接只能是一对一的,UDP 支持一对一,一对多,多对一和多对多的交互通信。
UDP 分组首部开销小,TCP 首部开销 20 字节,UDP 的首部开销小,只有 8 个字节。
TCP 面向字节流,实际上是 TCP 把数据看成一连串无结构的字节流,UDP 是面向报文的一次交付一个完整的报文,报文不可分割,报文是 UDP 数据报处理的最小单位。
UDP 适合一次性传输较小数据的网络应用,如 DNS,SNMP 等。
校验和:TCP 将保持它首部和数据的检验和。这是一个端到端的检验和,目的是检测数据在传输过程中的任何变化。如果收到段的检验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段。
序列号:TCP 传输时将每个字节的数据都进行了编号,这就是序列号。(为了应对延时抵达和排序混乱)。每个连接都会选择一个初始序列号,初始序列号(视为一个 32 位计数器),会随时间而改变(每 4 微秒加 1)。因此,每一个连接都拥有不同的序列号。序列号的作用不仅仅是应答的作用,有了序列号能够将接收到的数据根据序列号排序,并且去掉重复序列号的数据。这也是 TCP 传输可靠性的保证之一。
确认应答:TCP 传输的过程中,每次接收方收到数据后,都会对传输方进行确认应答。也就是发送 ACK 报文。这个 ACK 报文当中带有对应的确认序列号,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。
超时重传:超时重传机制。简单理解就是发送方在发送完数据后等待一个时间,时间到达没有接收到 ACK 报文,那么对刚才发送的数据进行重新发送。如果是刚才第一个原因,接收方收到二次重发的数据后,便进行 ACK 应答。如果是第二个原因,接收方发现接收的数据已存在(判断存在的根据就是序列号,所以上面说序列号还有去除重复数据的作用),那么直接丢弃,仍旧发送 ACK 应答。那么发送方发送完毕后等待的时间是多少呢?如果这个等待的时间过长,那么会影响 TCP 传输的整体效率,如果等待时间过短,又会导致频繁的发送重复的包。如何权衡?由于 TCP 传输时保证能够在任何环境下都有一个高性能的通信,因此这个最大超时时间(也就是等待的时间)是动态计算的。
连接管理:说白了就是三次握手四次挥手。
流量控制:当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。
拥塞控制:拥塞控制是 TCP 在传输时尽可能快的将数据传输,并且避免拥塞造成的一系列问题。是可靠性的保证,同时也是维护了传输的高效性。
1) select
fd_set 使用数组实现
1 fd_size 有限制 1024 bitmap,fd[i] = accept()
2 fdset不可重用,新的fd进来,重新创建
3 用户态和内核态拷贝产生开销
4 O(n)时间复杂度的轮询
结果:成功调用返回结果大于 0,出错返回结果为 -1,超时返回结果为 0
返回:具有超时时间
2) poll
基于结构体存储fd
struct pollfd{
int fd;
short events;
short revents; //可重用
}
解决了select的1,2两点缺点
3) epoll
解决select的1,2,3,4;
不需要轮询,时间复杂度为O(1);
epoll_create 创建一个白板 存放fd_events;
epoll_ctl 用于向内核注册新的描述符或者是改变某个文件描述符的状态。已注册的描述符在内核中会被维护在一棵红黑树上;
epoll_wait 通过回调函数内核会将 I/O 准备好的描述符加入到一个链表中管理,进程调用 epoll_wait() 便可以得到事件完成的描述符;
两种触发模式:
LT:水平触发
当 epoll_wait() 检测到描述符事件到达时,将此事件通知进程,进程可以不立即处理该事件,下次调用 epoll_wait() 会再次通知进程。是默认的一种模式,并且同时支持 Blocking 和 No-Blocking。
ET:边缘触发
和 LT 模式不同的是,通知之后进程必须立即处理事件。
下次再调用 epoll_wait() 时不会再得到事件到达的通知。很大程度上减少了 epoll 事件被重复触发的次数,
因此效率要比 LT 模式高。只支持 No-Blocking,以避免由于一个文件句柄的阻塞读/阻塞写操作把处理多个文件描述符的任务饿死。
————————————————
版权声明:本文为CSDN博主「相偎」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https:///u013932564/article/details/127227091
1、通过网络,要发送哪些数据,比如至少得发送类名或者接口名,要调用的方法名、调用方法时传入的参数等。
2、方法参数如果是对象,那么如果要考虑网络发送对象的问题,就需要考虑序列化和反序列化的问题了,使用何种序列化机制,也是要考虑的问题。
3、确定好了要发送的数据后,那通过什么方式发出去呢,是直接通过Socket发送,或者是http发送呢。
4、如果利用http来发,那就是用http1.1,或者是http2呢,请求头放什么数据,请求体放什么数据,都是问题。
5、如何直接通过socket来发,那就需要自己设计一个数据格式了,类似于htp协议,不然服务器接收到字节流之后无法解析字节流。
6、确定好数据格式和网络传输方式之后,就需要考虑是否支持异步功能了,是否支持回调功能。
7、另外想负载均衡、服务容错、服务路由、服务重试等功能也要逐一考虑。
————————————————
版权声明:本文为CSDN博主「一只傻阿Z」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https:///qq_34069570/article/details/128111786
三次握手:
1、刚开始客户端和服务端都是处于关闭的状态,而且服务器 B 端一直处于监听的状态,时刻监听是否有建立连接的请求;
2、当有客户端需要建立连接的时候就会发送一个确定连接的报文,此报文是同步报文SYN = 1,并且会生成一个随机的序号 seq = x,这是第一次握手;
3、当服务端接收到请求连接报文的时候,会发送一个同步报文确认报文,此报文 SYN = 1,并且 ACK = 1,同时服务端也会随机生成一个 seq = y,并将 ack 设置成 x + 1,回传给客户端,这是第二次握手;
4、当客户端接收到服务端的 ACK 报文后,会回复一个 ACK 确认报文,用于确认确认报文已经收到,此报文 ACK = 1,seq = x + 1, ack = y + 1,这是第三次握手;
这里有个点说明一下:大写的 ACK 表示报文的类型是确认报文,小写的 ack 是报文里面的确认号,这个确认号是上一次握手对方的 seq 值加 1 得到。
第一次握手:第一次握手是客户端发送同步报文到服务端,这个时候客户端是知道自己具备发送数据的能力的,但是不知道服务端是否有接收和发送数据的能力;
第二次握手:当服务端接收到同步报文后,回复确认同步报文,此时服务端是知道客户端具有发送报文的能力,并且知道自己具有接收和发送数据的能力,但是并不知道客户端是否有接收数据的能力;
第三次握手:当客户端收到服务端的确认报文后,知道服务端具备接收和发送数据的能力,但是此时服务端并不知道自己具有接收的能力,所以还需要发送一个确认报文,告知服务端自己是具有接收能力的。
四次挥手:
1、客户端发起 FIN 断开连接的报文,携带随机生成的 seq 值 u,发送给服务端,并且自己处于 FIN-WSIT 状态,这是第一次挥手;
2、服务端接收到 FIN 报文后,回复一个确认报文,其中 ACK = 1,随机生成一个 seq,以及 ack = u + 1,这是第二次挥手;
3、当服务端数据发送完了过后,再发送一个 FIN 报文给客户端,通知客户端,服务端准备关闭连接了,此报文 FIN = 1,ACK = 1,ack = u + 1,seq = w,这是第三次挥手;
4、当客户端收到 FIN 确认报文时再发送一个FIN 的确认报文,其中 ACK = 1,seq = u + 1,ack = w + 1,并进入 TIME-WAIT 状态,当等待 2MSL 后关闭连接,这是第四次挥手。
第一次挥手客户端发起关闭连接的请求给服务端;
第二次挥手:服务端收到关闭请求的时候可能这个时候数据还没发送完,所以服务端会先回复一个确认报文,表示自己知道客户端想要关闭连接了,但是因为数据还没传输完,所以还需要等待;
第三次挥手:当数据传输完了,服务端会主动发送一个 FIN 报文,告诉客户端,表示数据已经发送完了,服务端这边准备关闭连接了。
第四次挥手:当客户端收到服务端的 FIN 报文过后,会回复一个 ACK 报文,告诉服务端自己知道了,再等待一会就关闭连接。
1、首先呢,客户端先向服务端发送加密通信(https)请求,这次请求中包括:
SSL/TSL版本号
加密套件,也就是客户端支持的加密算法列表
产生一个随机数,我们叫他为第1随机数
有一个Client Hello字符串
2、服务器收到请求后,向客户端发出响应:
确认SSL/TSL版本号,如果客户端不支持,那么就关闭通信
确认的加密算法列表
生成一个随机数,我们叫第2随机数
3、服务器再向客户端发送数字证书,这里敲重点了。服务器会把自己的公钥注册到CA(第三方证书机构),然后CA拿自己的私钥对服务器的公钥进行处理并颁发数字证书。
4、服务器将公钥发送给客户端
5、服务器发送Hello Done,表示发送完毕
6、客户端收到服务端一系列响应后,确认数字证书和公钥,没有问题后向服务端发送:
生成一个随机数,我们叫第3随机数或者预主密钥,此预主密钥会通过公钥进行加密
客户端握手结束通知,表示客户端的握手结束
7、服务端收到客户端数据后,使用私钥对加密后的预主密钥进行解密,没有其他人知道预主密钥,因为它加密了,除非服务器私钥泄漏。然后服务端通过第一、二、预主密钥计算出会话密钥。客户端也计算出了会话密钥。
8、服务端向客户端发送:
加密通信算法改变通知,以后通过会话密钥通信
服务端握手结束
到此为止,SSL/TSL握手结束,在此之后都会通过会话密钥来进行加密和解密,也就是对称加密。
————————————————
版权声明:本文为CSDN博主「兴涛」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https:///m0_46672151/article/details/123744429
首先,在浏览器地址栏中输入url
浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若 没有,则跳到第三步操作。
在发送http请求前,需要域名解析(DNS解析),解析获取相应的IP地址。
浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。
握手成功后,浏览器向服务器发送http请求,请求数据包。
服务器处理收到的请求,将数据返回至浏览器
关闭TCP连接(四次挥手)
浏览器收到响应结果解析html代码并请求资源(js、css、图片等)
浏览器进行页面布局渲染
————————————————
版权声明:本文为CSDN博主「小栗子~」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https:///weixin_52793430/article/details/124488142
git解决冲突有两种办法:
rebase
merge
先说结论,解决冲突时尽量使用rebase。原因是因为rebase可以使得提交历史更加清晰,代码更加健壮。
rebase与merge的区别:
rebase:重定义起点,相当于将冲突分支整体“迁移”至另一分支上。
merge:聚合分支,将冲突分支和另一分支“聚合”合并至新节点上。
区别:
1、不同于 git rebase的是,git merge 在不是 fast-forward(快速合并)的情况下,会产生一条额外的合并记录,类似Merge branch 'xxx' into 'xxx'的一条提交信息。
2、另外,在解决冲突的时候,用 merge 只需要解决一次冲突即可,简单粗暴,而用 rebase 的时候 ,需要一次又一次的解决冲突。
TTL 接口定义:TTL key
接口描述:获取key的过期时间。如果key存在过期时间,返回剩余生存时间(秒);如果key是永久的,返回-1;如果key不存在或者已过期,返回-2。
PTTL 接口定义:PTTL key
接口描述:获取key的过期时间。如果key存在过期时间,返回剩余生存时间(毫秒);如果key是永久的,返回-1;如果key不存在或者已过期,返回-2。
作者:啊强啊
链接:https://www.zhihu.com/question/452104902/answer/1809457553
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
从内存占用上来比较,跳表比平衡树更灵活一些。平衡树每个节点包含 2 个指针(分别指向左右子树),而跳表每个节点包含的指针数目平均为 1/(1-p),具体取决于参数 p 的大小。如果像 Redis里的实现一样,取 p=1/4,那么平均每个节点包含 1.33 个指针,比平衡树更有优势。
在做范围查找的时候,跳表比平衡树操作要简单。在平衡树上,我们找到指定范围的小值之后,还需要以中序遍历的顺序继续寻找其它不超过大值的节点。如果不对平衡树进行一定的改造,这里的中序遍历并不容易实现。而在跳表上进行范围查找就非常简单,只需要在找到小值之后,对第 1 层链表进行若干步的遍历就可以实现。
从算法实现难度上来比较,跳表比平衡树要简单得多。平衡树的插入和删除操作可能引发子树的调整,逻辑复杂,而跳表的插入和删除只需要修改相邻节点的指针,操作简单又快速。
虽然有多种不同单位和不同形式的设置命令,但实际上 EXPIRE、PEXPIRE、EXPIREAT 三个命令都是使用PEXPIREAT 命令来实现的:无论客户端执行的是以上四个命令中的哪一个,经过转换之后,最终的执行效果都和执行 PEXPIREAT 命令一样。
redisDb 结构的 expires 字典保存了数据库中所有键的过期时间,我们称这个字典为过期字典
过期字典的键是一个指针,这个指针指向键空间中的某个键对象(也即是某个数据库键)。
过期字典的值是一个 long long 类型的整数,这个整数保存了键所指向的数据库键的过期时间——一个毫秒精度的 UNIX 时间戳。
Redis 采用的过期策略:
懒汉式删除+定期删除
懒汉式删除流程:
1、在进行 get 或 setnx 等操作时,先检查 key 是否过期;
2、若过期,删除 key,然后执行相应操作;
3、若没过期,直接执行相应操作;
4、定期删除流程(简单而言,对指定个数个库的每一个库随机删除小于等于指定个数个过期 key):
5、遍历每个数据库(就是 redis.conf 中配置的 ”database” 数量,默认为 16)
6、检查当前库中的指定个数个 key(默认是每个库检查 20 个 key,注意相当于该循环执行 20 次,循环体是下边的描述)
7、如果当前库中没有一个 key 设置了过期时间,直接执行下一个库的遍历
8、随机获取一个设置了过期时间的 key,检查该key是否过期,如果过期,删除 key
9、判断定期删除操作是否已经达到指定时长,若已经达到,直接退出定期删除。
覆盖索引(covering index ,或称为索引覆盖)即从非主键索引中就能查到的记录,
而不需要查询主键索引中的记录,避免了回表的产生减少了树的搜索次数,显著提升性能。
管道的本质就是内核在内存中开辟了一个缓冲区,这个缓冲区与管道文件相关联,对管道文件的操作
,被内核转换成对这块缓冲区的操作。
父进程经过fork()以后,父进程和子进程拥有相同内容的代码段、数据段和用户堆栈,就像父进程把自己克隆了一遍。事实上,父进程只复制了自己的PCB块。而代码段,数据段和用户堆栈内存空间并没有复制一份,而是与子进程共享。只有当子进程在运行中出现写操作时,才会产生中断,并为子进程分配内存空间。
————————————————
版权声明:本文为CSDN博主「qq_42270373」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https:///qq_42270373/article/details/97264001
讲一下k8s、有哪些组件和作用
Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单高效,Kubernetes提供了应用部署、规划、更新、维护的一种机制。
1、kube-apiserver是整个K8S集群中,与Etcd直接交互,控制着集群中核心资源变化,提供了K8S各类资源对象(pod,RC,Service等)的增删改查及watch等HTTP Rest接口,是整个系统的数据总线和数据中心。
2、Kube-scheduler调度器是一个控制面进程,负责将 Pods 指派到节点上。 调度器基于约束和可用资源为调度队列中每个 Pod 确定其可合法放置的节点。 调度器之后对所有合法的节点进行排序,将 Pod 绑定到一个合适的节点。
3、Controller Manager作为集群内部的管理控制中心,负责集群内的Node、Pod副本、服务端点(Endpoint)、命名空间(Namespace)、服务账号(ServiceAccount)、资源定额(ResourceQuota)的管理,当某个Node意外宕机时,Controller Manager会及时发现并执行自动化修复流程,确保集群始终处于预期的工作状态。
4、Kubernetes网络代理运行在node 上,它反映了node 上 Kubernetes API中定义的服务,并可以通过一组后端进行简单的TCP、UDP和 SCTP流转发或者在一组后端进行循环TCP、UDP和 SCTP 转发,用户必须使用apiserver API创建一个服务来配置代理,其实就是kube-proxy通过在主机上维护网络规则并执行连接转发来实现Kubernetes服务访问。
5、Kubelet 是 kubernetes 工作节点上的一个代理组件,运行在每个节点上,监视已经分配给节点的Pod
6、kubectl 是 Kubernetes 的命令行工具(CLI),是 Kubernetes 用户和管理员必备的管理工具。
7、Dashboard是基于网页的Kubernetes用户界面,可以使用Dashboard获取运行在集群中的应用的概览信息,也可以创建或者修改Kubernetes资源(如Deployment, Job,DaemonSet 等等),也可以对Deployment实现弹性伸缩、发起滚动升级、重启 Pod或者使用向导创建新的应用。
Redis如何解决大key的问题
Redis使用者应该都遇到过大key相关的场景,比如:
1、热门话题下评论、答案排序场景。
2、大V的粉丝列表。
3、使用不恰当,或者对业务预估不准确、不及时进行处理垃圾数据等。
本质上指的是这个大key的value值过大
对大key进行拆分处理
我们可以将大key的键值对拆分,首先将value按照一定的规则拆分开来,按照key-value的方式存储起来,然后在将这些key按照一定的规则替换掉我们大key中的value,这样其实就是变相的将大key拆分了,我们存储的只是多个key。
这样,拿到了大key的值后,在遍历获取对应的value即可。
对大key的value值进行压缩处理
我们可以使用序列化技术对我们的value进行压缩处理,这样便可缩小value的空间,使其达到合理的范围标准。这样也就完成了处理!
对大key做有效时间的优化
对我们大key做有效时间的控制,使其在超过了自己的失效,自动释放,来减少大key的危害。当我们发现做完压缩处理之后,数据依旧无法达到我们的标准,这时候,我们可以采用第一种方法继续处理,对其进行拆分,以达到我们的标准。
监控Redis的使用情况
可以用系统自带的功能,或者我们自己开发一套监控系统,来定时监控Redis的使用率,内存占用情况!如发现内存占用较多,或者短时间内内存增长过快,我们就要及时干预!
以上方法中,前三种都是针对大key的本质来处理,减少value的过载,第四种就是我们运用一些辅助手段来完成监控及干预!
————————————————
版权声明:本文为CSDN博主「ybb_ymm」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https:///ybb_ymm/article/details/128451485