白话TCP/IP原理

TCP/IP(Transmission-Control-Protocol/Internet-Protocol),中文译名为传输控制协议/因特网互联协议,又名网络通讯协议,是Internet最基本的协议、也是Internet国际互联网络的基础。

这是我上大学时的必修课。下班后我又看了一遍,认为我比在学校时理解得更多。但书中的东西毕竟不适合这项工作。本文结合工作中常用的几个方面和现实中出现的网上问题进行说明。

[En]

It was a required course when I was in college. I watched it again after work and thought I understood more than I did when I was at school. But the things in the books are not suitable for the work after all. This article combines the commonly used aspects of the work and the online problems that have appeared in reality to explain.

TCP/IP协议栈为什么是”栈”?

大学的时候课本上讲过:开放系统互联参考模型OSI/RM分7层,从低到高分别是物理层,数据链路层,网络层,传输层,会话层,表示层和应用层。

先从7层模型入手,是因为下面讲的TCP/IP四层模型里缺少咱们平时工作中常用的RPC远程过程调用协议,它工作在会话层,基于下面图中的socket来实现。

白话TCP/IP原理

实际上互联网通信使用的是TCP/IP协议栈。这里举例来说明为什么叫”栈”。

栈是一种先进后出的数据结构。拿一个HTTP报文来说,HTTP报文属于应用层协议的报文,我们输入网址,首先会调用到DNS协议(域名协议)。HTTP报文在传输层用的是TCP协议,我们把TCP压入栈中,再将IP层也压入栈中。链路层的话,就用最常见的以太网。

好了,现在我们的堆栈从头到尾是:

[En]

All right, now our stack is from beginning to end:

HTTP协议-TCP协议-IP协议-以太帧头

然后我们先忽略最底层的物理层,假设这个封装好的栈一样的报文漂洋过海,来到了它的目的地。对端收到这个报文以后,也就是我们封装好的这个栈一样的东西以后该怎么办呢?会不会也是先拿HTTP呢?因为这个报文是我们构造的一个栈,所以说它的顺序肯定也是栈。

因此拿取的顺序就是:

以太帧头-IP协议-TCP协议-HTTP协议

《接下来一段时间会对大家进行网络通信的魔鬼训练-理解socket》中我讲过:传输层操作是在内核空间完成的,就是说不是靠咱们平时的应用编码可以直接介入的。咱们平时直接用的就是应用层协议。想通过应用层操作传输层怎么办呢?这就用到了socket编程。因为HTTP协议的内容被封装进入了socket。这里称为套接字层。总体示意图如下:

白话TCP/IP原理

发现没,最先被封装入的HTTP报文(套接字层)是最后才被拿走的。

TCP三次握手和四次挥手

三次握手

《懂得三境界-使用dubbo时请求超过问题》这篇文章中,我讲过三次握手。这里用打比方的方式再讲一遍:

我在《两地书–K8s基础知识》里讲过司马相如和卓文君的故事。其实在巜史记》和《汉书》里有记载说:他们的爱情是一场精心策划的阴谋。

司马相如从一开始就计划找一个有钱的女人。因此,与当地县长一起,县长经常去看望司马相如,但司马相如避而不谈。但县长仍然每天都来。它的意思是照顾好小屋。当地人说这个人这么受县长的宠爱,肯定不容易。

[En]

Sima Xiangru planned to find a rich woman from the very beginning. Therefore, with the local county magistrate, the county magistrate often visited Sima Xiangru, but Sima Xiangru avoided it. But the county magistrate still comes every day. It means to take care of the cottage. It must not be easy for the local people to say that this man is so favored by the county magistrate.

卓文军的父亲是该地区最富有的人。听说后,他邀请司马相如做客。司马相如在宴会上的目标是与卓文俊建立通信。他仔细算了一下,卓文军的丈夫刚刚去世,被带回了娘家。不像一个还没出柜的女孩那么挑剔。我很端庄,很优雅。我想我们能处理好的。

[En]

Zhuo Wenjun’s father is the richest man in the area. When he heard about it, he invited Sima Xiangru to be a guest. Sima Xiangru’s goal at the banquet is to establish correspondence with Zhuo Wenjun. He carefully calculated that Zhuo Wenjun’s husband had just died and was taken back to his mother’s house. Not as picky as a girl who hasn’t come out of the cabinet. I am dignified and elegant. I think we can handle it.

但为什么他是唯一一个想和有钱女人在一起的人?他精心准备了一首《凤凰换凤凰》,第一次向卓文军发出建立通信的请求。

[En]

But why is he the only one who wants to be with a rich woman? He carefully prepared a song “the Phoenix for the Phoenix” and sent a request to Zhuo Wenjun to establish a communication for the first time.

白话TCP/IP原理

第一次握手时,客户司马相如提出了要求。在服务器端,卓文军只有一个进程来处理所有连接请求,处理能力有限。因此,这个人才和那个人才的联系请求会先放入队列,服务器会按顺序处理申请。

[En]

The first handshake, the client Sima Xiangru issued a request. On the server side, Zhuo Wenjun has only one process to handle all connection requests, which has limited processing capacity. Therefore, the contact request of this talent and that talent will be put into the queue first, and the server will process the application in order.

服务端卓文君收到客户端司马相如的申请,会验证收到的信息是否有误(实际TCP中检验的是通信数据是否有错误)。无误则对这个客户端的状态变成listen状态,并向司马相如发出一个回执:”你的琴弹的不错,可以建立联系。”这就是第二次握手。

客户端司马相如收到服务端卓文君的回执,认为自己的目的已达到,把自己标记为established状态,并进行第三次握手:”好的,仰慕已久。”这时候客户端已经一厢情愿的认为自己可以自由与服务端通信了。

然而,服务器端卓文军仍在与客户端司马相如建立连接,请求在满连接队列中排队。毕竟,有很多有才华的人需要打交道。客户司马相如的收据还在排队等待,卓文军还没有办理。所以这个时候,如果客户司马相如发了一封信(传输数据)。卓文军没有告诉他的女仆,他已经与当事人的司马相如建立了联系。因此,这封信根本无法到达卓文军手中。这封信未能寄出。

[En]

However, the server side Zhuo Wenjun is still in the process of establishing a connection with the client Sima Xiangru, and the request is queued in the full connection queue. After all, there are a lot of talented people to deal with. Client Sima Xiangru’s receipt is still waiting in line, and Zhuo Wenjun hasn’t dealt with it yet. So at this time, if the client Sima Xiangru sent a letter (transmitted data). Zhuo Wenjun has not told his servant girl that he has established contact with Sima Xiangru of the client. Therefore, the letter can not reach Zhuo Wenjun at all. The letter failed to be sent.

等待服务器卓文军处理对客户端司马相如的请求,并真正建立连接。司马相如的信果然到了卓文君手里。到达了司马相如的第一步。

[En]

Wait for the server Zhuo Wenjun to process the request to the client Sima Xiangru, and really establish the connection. Sima Xiangru’s letter really reached Zhuo Wenjun. Reached the first step of Sima Xiangru.

后来,司马相如要求卓文俊与他私奔。回到司马相如老家,卓文军发现司马相如家里一贫如洗。卓文军向家人要钱,家人拒绝给。司马相如把卓文君带回了卓文君的老家,让卓文君当众卖酒。为了树立起文俊父亲的模样,让他的父亲感到无耻,主动给钱。

[En]

Later, Sima Xiangru asked Zhuo Wenjun to elope with him. When they returned to Sima Xiangru’s hometown, Zhuo Wenjun found that Sima Xiangru’s family was destitute. Zhuo Wenjun asked her family for money, but her family refused to give it. Sima Xiangru took Zhuo Wenjun back to Zhuo Wenjun’s hometown and let Zhuo Wenjun sell wine in public. In order to set the pattern of Wen Jun’s father, let his father feel shameless and take the initiative to give money.

司马相如的计划成功了,文军的父亲给了他们一大笔钱,让他们回司马相如的老家生活。但钱花得又快又花得大手大脚。司马相如去北京找钱。

[En]

Sima Xiangru’s plan succeeded, and Wenjun’s father gave them a wealth of money and asked them to go back to Sima Xiangru’s hometown to live. But the money was spent lavishly and quickly. Sima Xiangru went to Beijing to look for money.

四次挥手

白话TCP/IP原理

这次司马相如果然得到了汉武帝赏识。司马相如发达了就想休妻再娶。终于某日,客户端司马相如给服务端卓文君送出了一封十三字的分手信:”一二三四五六七八九十百千万。” 无亿,就是说我就你已经无意啦。这就是第一次挥手。实际上第一次挥手会告诉服务端如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。

服务端卓文君收到这个消息,非常震惊。她还没有准备好。于是,先回复了一个消息让客户端司马相如等一等。这就是第二次挥手。(这个时候客户端就进入FIN_WAIT状态,继续等待服务端的FIN报文。)

此时,他们仍然是夫妻。服务器端的卓文俊可以继续向客户端司马相如发送消息。服务员卓文君首先回复了一首《怨郎》:

[En]

At this time, they are still husband and wife. The server Zhuo Wenjun can continue to send messages to the client Sima Xiangru. Zhuo Wenjun, the server, first replied to a poem of “resentment Lang”:

别之后,
地相思,
只道是 三四月,
又谁知 五六年。
弦琴无心弹,
行书无可传,
曲连环从中折断,
里长亭望眼欲穿。
思想,
系念,
般无奈把君怨。
语千言说不完,
无聊赖 倚栏。
登高看孤雁,
月中秋月圆人不圆。
月半,秉烛烧香问苍天。
月伏天人人摇扇我心寒。
月石榴似火红,偏遭阵阵冷雨浇花端。
月枇杷未黄,我欲对镜心意乱。
急匆匆, 月桃花随水转;
飘零零, 月风筝线儿断。
噫,郎呀郎,恨不得下 世,你为女来我做男。

当服务生卓文军说完想说的话时,他回复了客户司马相如:我听说你有两个想法,所以我会拒绝。(摘自“白头银”)意思是我准备好了,既然你改变主意了,那就算了吧。这是第三波。

[En]

When the server Zhuo Wenjun finished what he wanted to say, he replied to the client Sima Xiangru: “I hear that you have two ideas, so I will refuse.” (from “White head Yin”) it means I’m ready, and since you’ve changed your mind, let’s forget it. This is the third wave.

这时候,如果客户端司马相如是一般人,得偿所愿了。就会回复一个:”祝你幸福。”这是韩剧里标准的分手时最后话术,是通知服务端彻底断绝关系的。然后再等等确认服务端彻底没有反馈就是分手成功了。这就是第四次挥手。(实际上客户端收到FIN报文后,就知道可以关闭连接了,但是它还是不相信网络,怕服务端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果服务端没有收到ACK则可以重传。)

但司马相如是一位艺术家。艺术家们最害怕去掉粉末。想司马相如的钱主要靠《龙门赋》,这是用来还原怨妇情怀的诗歌。这么铁石心肠,谁会买那首诗呢?有多少政要会被冒犯。更何况,卓文君和白头银的这两首诗太出彩了!像司马相如一样聪明的人立刻知道,如果他不继续保持这个才子佳人的故事,他的职业生涯就会消失。因此,他选择重新三次握手来建立联系。

[En]

But Sima Xiangru is an artist. Artists are most afraid of powder removal. Think about Sima Xiangru’s money mainly depends on the “long door Fu”, which is used to restore feelings of resentful woman poetry. With such a heart of stone, who would buy that poem? How many dignitaries will be offended. What’s more, these two poems written by Zhuo Wenjun and Bai Tou Yin are so outstanding! As smart as Sima Xiangru immediately knew that if he did not continue to maintain this story of gifted scholars and beauties, his career would be gone. So he chose to renew the three-way handshake to establish the connection.

TCP长连接和短连接

TCP连接有三次握手和四次挥手的加持,被称为可靠的连接。UDP这样的数据报被称为不可靠的连接。可靠就有代价。

白话TCP/IP原理

长连接和短连接之间的本质区别如上图所示。短连接的每次通信都伴随着三次握手和四次波,而长连接则重复使用这两个过程。为了实现效益最大化、成本最小化,不同的应用场景会选择使用长连接或短连接。

[En]

The essential difference between long connections and short connections is shown in the figure above. Each communication of a short connection is accompanied by three handshakes and four waves, while a long connection reuses these two processes. In order to maximize benefits and minimize costs, different application scenarios will choose to use long or short connections.

长连接和短连接各自的优缺点

  • 长连接可以省去较多的TCP建立和关闭的操作,减少浪费,节约时间,但是一直连接对于客户端来说比较耗电。
  • 持久连接更适合频繁请求资源的客户端。
    [En]

    persistent connections are more suitable for clients that frequently request resources.*

  • 如果客户端和服务器之间的连接不是一直关闭,就会出现问题:随着客户端连接越来越多,服务器迟早会无法处理,服务器需要采取一些策略。例如,关闭一些长时间没有读写事件的连接,以防止一些恶意连接对服务器服务造成损害。
    [En]

    if the connection between the client and the server is not closed all the time, there will be a problem: with more and more client connections, the server will be unable to handle it sooner or later, and the server needs to adopt some strategies. For example, close some connections that do not have read and write events for a long time, so as to prevent some malicious connections from causing damage to the server service.*

  • 在条件允许的情况下,可以以客户端机器为粒度,限制每个客户端的最大长连接数,完全避免部分客户端出现问题时服务器受到影响。
    [En]

    if the conditions permit, you can use the client machine as the granularity to limit the maximum number of long connections per client, so as to completely prevent the server from being affected if something goes wrong with some clients.*

  • 服务器的短连接管理相对简单。现有的连接是有用的连接,不需要额外的控制。
    [En]

    short connections are relatively simple to manage for the server. Existing connections are useful connections and no additional control is required.*

  • 一次TCP连接和断开需要7个来回,如果客户端请求频繁,将在TCP的建立和关闭操作上浪费大量时间和带宽。

短连接应用场景

一般网站类的web服务都是短连接。试想一个普通网站,比如查看我这篇公众号文章,总共有6000多个字。一旦打开,内容加载完之后,很长时间不用再次传输数据。那占着连接是不是很浪费?

而且服务端可承载的最大连接数是有限的,不然文件句柄不够用啊。一个网站希望用几十、几百台4核8G就可以支撑日活几百万,那最好使用短连接。

长连接应用场景

公司内的各个系统之间使用RPC。大家使用的工具不太相同,有的公司自己基于thrift协议进行开发,有的使用开源的Dubbo。但是大家都头脑清醒的使用了长连接。

因为在内部场景中,上下游是固定的,连接的客户端数量是相对固定的。长连接节省了建立连接的开销,并且可以直接根据请求数量进行数据传输。

[En]

Because in the internal scenario, the upstream and downstream are fixed, and the number of clients connected is relatively fixed. Long connections save the overhead of connection establishment, and data transmission can be carried out directly with the number of requests.

公司内部使用的中间件也大多使用长连接。例如:MQ、k8s、Redis、mysql。提到这些不得不提相关的两个技术。

keepalive保活机制

KeepAlive并不是TCP协议规范的一部分,但在几乎所有的TCP/IP协议栈(不管是Linux还是Windows)中,都实现了KeepAlive功能。

先看看使用场景:

白话TCP/IP原理

我没看过这部电影,也不知道是哪部电影。我只知道张艺谋在楼下不停地喊着《安红我想你》。这一幕风靡了一段时间。

[En]

I haven’t seen this movie, and I don’t know which movie it is. I just know that Zhang Yimou kept shouting “an Hong I miss you” downstairs. This scene was very popular for some time.

客户张艺谋发了一条信息。收到消息后,服务器看了一眼,给了你,然后忽略了客户端。这只愚蠢的狗客户一直在等,但我不知道服务器是不是坏了。

[En]

The client Zhang Yimou sent a message. After receiving the message, the server took a look at it and gave it to you, and then ignored the client. The stupid dog client has been waiting, but I don’t know if the server is down.

这时候TCP协议提出一个办法,当客户端端等待超过一定时间后自动给服务端发送一个空的报文,如果对方回复了这个报文证明连接还存活着,如果对方没有报文返回且进行了多次尝试都是一样,那么就认为连接已经丢失,客户端就没必要继续保持连接了。如果没有这种机制就会有很多空闲的连接占用着系统资源。原理如下图:

白话TCP/IP原理

如何设置它?

在设置之前我们先来看看KeepAlive都支持哪些设置项

  • KeepAlive默认情况下是关闭的,上层应用可以通过开关来开启和关闭
  • tcp_keepalive_time: KeepAlive的空闲时长,或者说每次正常发送心跳的周期,默认值为7200s(2小时)
  • tcp_keepalive_intvl: KeepAlive探测包的发送间隔,默认值为75s
  • tcp_keepalive_probes: 在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包次数,默认值为9(次)

我们讲讲在Linux操作系统和使用Java如何设置。

在Linux内核设置

KeepAlive默认不是开启的,如果想使用KeepAlive,需要在你的应用中设置SO_KEEPALIVE才可以生效。

查看当前的配置:

cat /proc/sys/net/ipv4/tcp_keepalive_time<br>cat /proc/sys/net/ipv4/tcp_keepalive_intvl<br>cat /proc/sys/net/ipv4/tcp_keepalive_probes

在Linux中我们可以通过修改 /etc/sysctl.conf 的全局配置:

net.ipv4.tcp_keepalive_time=7200<br>net.ipv4.tcp_keepalive_intvl=75<br>net.ipv4.tcp_keepalive_probes=9

添加上面的配置后输入 sysctl -p 使其生效,你可以使用 sysctl -a | grep keepalive 命令来查看当前的默认配置

如果应用中已经设置SO_KEEPALIVE,程序不用重启,内核直接生效

使用Netty4设置

这里我们使用常用的Java网络框架Netty来设置,只需要在服务端设置即可:

csharp;gutter:true; EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 100) .childOption(ChannelOption.SO_KEEPALIVE, true) .handler(new LoggingHandler(LogLevel.INFO));</p> <p>// Start the server.</p> <p>ChannelFuture f = b.bind(8088).sync(); // Wait until the server socket is closed.</p> <p>f.channel().closeFuture().sync(); } finally { // Shut down all event loops to terminate all threads.</p> <p>bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); }

这段代码来自经典的echo服务器,我们在childOption中开启了SO_KEEPALIVE。
Java程序只能做到设置SO_KEEPALIVE选项,其他配置项只能依赖于sysctl配置,系统进行读取。

使用的场景

一般我们使用KeepAlive时会修改空闲时长,避免资源浪费,系统内核会为每一个TCP连接建立一个保护记录,相对于应用层面效率更高。

常见的几种使用场景:

  • 检测失败的连接(原因很多,比如服务中断、网络波动、停机、应用重启等)
    [En]

    detect failed connections (there are many reasons for them, such as service stoppage, network fluctuation, downtime, application restart, etc.)*

  • 防止因为网络不活动而断连,如使用NAT代理或者防火墙的时候,经常会出现这种问题
  • HTTP协议的Keep-Alive意图在于连接复用,同一个连接上串行方式传递请求-响应数据
  • TCP的KeepAlive机制意图在于保活、心跳,检测连接错误

KeepAlive通过定时发送探测包来探测连接的对端是否存活,但通常也会许多在业务层面处理,他们之间的特点是:

  • TCP自带的KeepAlive使用简单,发送的数据包相比应用层心跳检测包更小,仅提供检测连接功能
  • 应用层心跳包不依赖于传输层协议,无论传输层协议是TCP还是UDP都可以用
  • 应用层心跳包可定制,以处理更复杂的情况或传输一些额外信息
    [En]

    the application layer heartbeat package can be customized to deal with more complex situations or transmit some additional information*

  • KeepAlive仅代表连接保持着,而心跳包往往还代表客户端可正常工作

像Dubbo这种通信中间件都使用到了TCP的保活机制。k8s客户端和服务端是基于http协议的长连接,用到了http的保活复用连接。

连接池技术

上面四次挥手讲了,如果服务器总是在断开连接,tcp会总是处于time wait状态。很多连接没有得到真正的释放。像数据库操作,是非常频繁的。咱们一般都不会像下图这么每次都申请和关闭连接吧。

白话TCP/IP原理

因此,我们希望尽可能地重用三次握手和四次握手的过程,使客户端和服务器在数据传输上投入更多的资源。需要连接池。

[En]

Therefore, we hope to reuse the process of three-way handshake and four waves as much as possible, so that the client and server invest more resources in data transmission. Connection pooling is needed.

连接池是一种池式结构。其他的池式结构有:线程池、协程池、内存池和对象池。它们的实现都很接近。连接池中也有很多大家听说过的场景,如:数据库连接池、MQ的连接池、Redis的连接池。

提到MQ的连接池,之前的时候,有个同事排查我们使用的MQ并发吞吐太低。因为用的是标准的Java消息服务JMS客户端,跟了代码发现里面用到了connection.close。就怀疑用的短连接。其实close方法的实现一般不是销毁连接,还是归还到连接池。

白话TCP/IP原理

我们平时使用连接池最多,最常用的是控制可伸缩性的参数:最小连接数、最大连接数。最小连接数主要是限制池的大小,最大连接数主要是限制可以打开的最大连接数。使用连接池进行通信的过程如下图所示:

[En]

Connection pool we usually use the most, the most interview is to control the scalability of the parameters: the minimum number of connections, the maximum number of connections. The minimum number of connections is mainly to limit the size of the pool, and the maximum number of connections is mainly limited to the maximum number of connections that can be opened. The process of communicating using connection pooling is shown in the following figure:

白话TCP/IP原理

我将写一篇关于连接池的文章,因为预计将超过2000字。

[En]

I will write an article about connection pooling because it is expected to be more than 2,000 words.

细思极恐的Socket

《接下来一段时间会对大家进行网络通信的魔鬼训练-理解socket》中我专门讲过socket,它功能强大但是让人细思极恐。之前发生过一个线上问题,某个时刻发生了几笔请求超时,排查发现打印Dubbo调用的来源IP时,触发了DNS反解析。网络闪断,连接不到DNS服务器,结果夯住10s直到超时。

熟悉Java语言的朋友可以了解一下当时线上问题的原因:

dubbo调用的来源IP使用的是dubbo的

RpcContext.getContext().getRemoteAddress().getHostName();

因为RpcContext.getContext()是基于上篇文章《ThreadLocal&MDC内存泄漏问题》中提到的ThreadLocal,就是保存在了线程里的一个固定值。所以也就相当于

new InetSocketAddress(固定的IP, 固定的端口).getHostName();

这个方法会进行DNS lookup!所以具体这个函数的执行时间受到网络状况的影响。建议可以直接使用IP的地方使用getAddress()代替getHostName()。

这个问题可以这样理解:

[En]

The question can be understood in this way:

相当于在程序里执行了一个linux命令:nslookup 某IP

白话TCP/IP原理

为什么说让人细思极恐呢?想想看,使用Socket编程,只需一行代码,有时候就是隐式的,实际上却可能发出了一个绕地球半圈的信号,关键多数开发者还不知道。

总结

如大家所见,本篇算是《白话linux操作系统原理》的姊妹篇。和《网络通信之Session的历史血脉》《深入理解MQ生产端的底层通信过程-理解channel》《接下来一段时间会对大家进行网络通信的魔鬼训练-理解socket》《网络字节序列-大端序和小端序》《https引起的跨域问题-COE&casestudy》《懂得三境界-使用dubbo时请求超过问题》《一个http请求进来都经过了什么(2021版)》《架构师之路-https底层原理》是一个系列。

在之前的文章中说过,我尽量想办法让大家能把这些系列文章有兴趣看下去。如果大家坚持下去,会对以后的工作有很大帮助。《白话linux操作系统原理》这篇文章发出之后,反馈特别好。我就在想是不是这里存在着可以让大家坚持下去的点。可是,我自己都没搞清楚这个点在哪里。

只要用心写作,你也对自己的知识和能力有信心,知道自己写的东西对每个人的知识和能力都很有帮助。那就坚持下去。我相信它能帮助大家,为祖国的科技发展做出贡献。

[En]

As long as you write attentively, you also have confidence in your knowledge and ability, and knowing what you write is very helpful to everyone’s knowledge and ability. Then stick to it. I believe it can help everyone and make a contribution to the scientific and technological development of the motherland.

Original: https://www.cnblogs.com/xiexj/p/15812832.html
Author: 编程一生
Title: 白话TCP/IP原理

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/524164/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • MacOS设置终端代理

    前言 国内的开发者或多或少都会因为网络而烦恼,因为一些特殊原因有时候网络不好的时候需要使用代理才能完成对应的操作。原来我一直都是使用斐讯路由器然后刷了梅林的固件,直接在路由器层面设…

    Linux 2023年6月14日
    076
  • Docker 安装 ElasticSearch 及失败解决方法[Ubuntu 20.04]

    1. 下载 ElasticSearch 最开始使用 docker search命令搜索后,就直接使用 docker pull命令拉取镜像,但没想到拉取失败,后来到官网看了看,原来没…

    Linux 2023年6月14日
    0123
  • 模型层

    准备阶段 django自带的sqlite3数据库,功能很少,并且针对日期类型不精确 准备步骤 数据库正向迁移命令(将类操作映射到表中) python3 manage.py make…

    Linux 2023年6月7日
    079
  • 2.VMware三种网络模式

    本文参考《Vmware虚拟机三种网络模式详解》、《网络原理,以及对VMware Workstation虚拟网络VMnet0、VMnet1、VMnet8的图解》 一.VMware的网…

    Linux 2023年5月27日
    0109
  • 【Leetcode】64. 最小路径和

    给定一个包含非负整数的 m&#xA0;x&#xA0;n网格 grid,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 说明:每次只能向下或者向右移动…

    Linux 2023年6月6日
    081
  • Java — 枚举

    枚举是 JDK5 中引入的特性,由 enum 关键字来定义一个枚举类。 格式: enum 枚举类名 { 枚举项1, 枚举项2, …; 成员变量; 构造方法 成员方法 } 说明:…

    Linux 2023年6月8日
    072
  • 统计Redis中各种数据的大小

    如果 MySQL 数据库比较大的话,很容易就能查出是哪些表占用的空间; 不过如果 Redis 内存比较大的话, […] Meet so Meet. C plusplus…

    Linux 2023年5月28日
    068
  • 【Example】C++ Vector 内存预分配的良好习惯

    为什么要对 Vector 进行内存预分配? 1,Vector 本身是一个内存只会增长不会减小的容器。 2,Vector 存在 size 和 capacity 两种计数,size 即…

    Linux 2023年6月13日
    080
  • boot issue

    Q:生产过程中不小心把 boot文件删除了 ,或者升级kenerl时发现版本不兼容,需要回退,此时没有快照备份情况如何操作? A:boot 主要文件是内核和grub引导文件 1.进…

    Linux 2023年6月6日
    098
  • shell的入门

    命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。 中间不能有空格,可以使用下划线 不能使用标点符号 不能使用bash里面关键字 使用变量加上$就可使用 只读变量 rea…

    Linux 2023年6月8日
    076
  • 个人超级计算机

    这篇文章是回答一位用户的问题。 问:站长,我是一个在读研究生,正在学习分布式计算、高性能集群计算方面的知识,Laxcus分布式操作系统也是我的学习模板之一,但是我发现,无论是编程开…

    Linux 2023年6月6日
    074
  • Linux安装cmatrix代码雨教程

    一:介绍 cmatrix代码雨是Linux的系统屏保界面;执行cmatrix不仅可以练习简单的编译安装软件三部曲,还可以执行cmatrix命令做出代码雨,提升文化实力 二:成品演示…

    Linux 2023年5月27日
    086
  • LeetCode-443. 压缩字符串

    题目来源 题目详情 给你一个字符数组 chars ,请使用下述算法压缩: 从一个空字符串 s 开始。对于 chars 中的每组 连续重复字符 : 如果这一组长度为 1 ,则将字符追…

    Linux 2023年6月7日
    089
  • 聊聊.netcore采坑那一些事之系统时间and文件路径

    聊聊 .netcore 采坑那一些事之系统时间and 文件路径 Hi,小伙伴大家好,最近工作比较忙,很久没有和大家分享点东西了。这个周末都加了两天班。公司的新项目都是采用.netc…

    Linux 2023年6月14日
    066
  • 大厂们的 redis 集群方案

    redis 集群方案主要有两类,一是使用类 codis 的架构,按组划分,实例之间互相独立;另一套是基于官方的 redis cluster 的方案;下面分别聊聊这两种方案; 类 c…

    Linux 2023年5月28日
    073
  • redis

    ./redis-cli -a 111 KEYS "key*" | xargs ./redis-cli -a 111 DEL Original: https://…

    Linux 2023年5月28日
    080
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球