高并发的哲学原理(五)-- 拆分网络单点(上):应用网关、负载均衡和路由器(网关)

news2024/11/26 22:22:34

上一篇文章的末尾,我们提到了一个假想出来的五万 QPS 的系统,以及这种规模的系统架构中必然存在的负载均衡器,那本篇文章我们就来一起利用负载均衡搭建一个能够支撑五万 QPS 的系统。

“监听 HTTPS 443 端口的进程”这个单点

之前,我们拆出了“监听 HTTPS 443 端口的进程”这个单点,并用 Kong 网关来承载了这个单点。目前,在 2 vCore 的虚拟机上,2000 QPS 的压力对应的大约是 20% 的 CPU 占用率,经过换算我们可以知道:假如 Kong 的性能可以随着核心数增加而线性提升的话,在维持最大 40% CPU 占用率的情况下,需要:

(50000 / 2000) * 2 * (20% / 40%) = 25 核

在这里我们先假设我们搞了一个 25 核的虚拟机,接住了这五万 QPS(实际上接不住,我们后面会说),那这个 Kong 网关到底是什么玩意儿呢?它就是标题中的“应用网关”。

应用网关

应用网关,又称 API 网关,顾名思义,它就是所有 API 请求的大门:自己接下所有的 HTTP/HTTPS/TCP 请求,再将请求转发给真正的上游服务器。而这些上游服务器可能是一堆虚拟机,也可能是一堆容器,甚至可以是多个数据中心各自的应用网关。由于应用网关做的事情非常少,所以它能支撑很高 QPS 的系统。

常见的应用网关软件有 HAProxy、Nginx、Envoy 等,而 Cisco、Juniper、F5 等一体化设备厂商也有相关的硬件产品。

应用网关除了提升系统容量外,还有很多别的优势。

1. 解放后端架构

经过对应用网关两年的使用,我现在认为所有系统都应该放在应用网关的背后,包括开发环境。

应用网关对后端架构的解放作用实在是太大了,可以让你在后端玩出花来:各种语言、各种技术、各种部署形式、甚至全国各地的机房都可以成为某条 URL 的最终真实服务方,让你的后端架构彻底起飞。

2. TLS 卸载

终端用户访问应用网关的时候采用的是 HTTPS 协议,这个协议是需要对数据进行加密解密的,应用网关非常适合干这件事情,而背后的业务系统只提供标准 HTTP 协议即可,降低了业务系统的部署复杂度和资源消耗。

3. 身份验证和安全性提升

应用网关可以对后端异构系统进行统一的身份验证,无需一个一个单独实现。也可以统一防火墙白名单,后端系统防火墙只对网关 ip 开放,极大提升了后端系统的安全性,降低了海量服务器安全管理的难度。甚至可以针对某条 API 进行单独鉴权,让系统的安全管控能力大幅提升。

4. 指标和数据收集

由于所有流量都会经过网关,所以对指标进行收集也变的简单了,你甚至可以将双向流量的内容全部记录下来,用于数据统计和安全分析。

5. 数据压缩与转换

应用网关还可以统一对流量进行 gzip 压缩,可以将所有业务一次性升级到 HTTP/2 和 HTTP/3,可以对数据进行格式转换(XML 到 JSON)和修改(增加/修改/删除字段),总之就是能各种上下其手,翻云覆雨,随心所欲。

负载均衡

应用网关的另一个价值就是负载均衡了:可以将请求的流量按照各种比例分发给不同的后端服务器,提升系统容量;可以做红蓝发布和金丝雀发布;可以针对流量特点做灰度发布;可以主动调节各个后端服务器的压力;屏蔽失效的后端服务器等等。

低负载下应用网关和负载均衡可以是同一个软件

虽然应用网关和负载均衡是两个不同的概念,但在低负载系统里,他们两个往往由同一个软件来扮演,例如前面说到的 Kong 网关就同时具备这两个功能。

拆分应用网关

一个五万 QPS 的系统,是无法使用 25 核的单机安装 Kong 网关来承载的,因为此时单机 TCP 连接数已经达到了十万以上,在这个条件下强如 Nginx 也达到性能极限了,性能不再增长甚至会开始下降,用户体验也会迅速变差。此时,我们需要对应用网关进行拆分。

应用网关怎么拆

逻辑上,应用网关执行的是“反向代理+数据过滤”任务,并没有要求应用网关只能由一台服务器来承接,换句话说,应用网关不是单点,只要多个节点的行为一致,那就可以共同承接这五万 QPS 的真实用户流量。

我们只需要在多台机器上装上同样版本的应用网关软件,然后在他们之间同步配置文件即可。Kong 采用的策略是让多个实例连接同一个PostgreSQL数据库,每五秒从数据库获取一次最新的配置,如果数据库挂掉,那就保持内存中的现有配置继续运行。

Kong 集群追求的是“最终一致性”,不追求五秒的得失,反而让系统格外地容易扩展,格外的健壮,最后一篇文章我们还会见到使用类似思维的“DNS 分布式拆分”。这个朴素的分布式架构颇有毛子暴力美学的风范,后面我们讨论列存储 ClickHouse 的时候还能见到。

如果单个应用网关扛不住五万 QPS,那我们搞一个负载均衡器放在应用网关的前面,架构图如下:

alt

分层的网络

负载均衡器为何能扛住五万 QPS?

看到这里有人可能会疑惑,既然单机的 Nginx 都顶不住五万 QPS 带来的 TCP 资源开销,那负载均衡器如何扛住呢?因为负载均衡器承载的是比 Nginx 所承载的 TCP 更下面一层的协议:IP 协议。

至此,我们正式进入了网络拆分之路,这条路很难走,但收益也会很大,最终我们将得到一个 200Gbps 带宽的软件定义负载均衡集群,让我们正式开始。

网络是分层的

alt
经典 TCP/IP 四层网络协议的首部

上面这张图引用自我的另一个系列文章:软件工程师需要了解的网络知识:从铜线到HTTP(三)—— TCP/IP¹。

如果你查看过网页的源代码,你就能知道网页背后是一段 HTML 代码,这段代码是被层层包裹之后,再在网络中传输的,就像上图中一样。以太网之所以拥有如此之强的扩展性和兼容能力,就是因为它的“分层特性”:每一层都有专门的硬件设备来对网络进行扩展,最终组成了这个容纳全球数十亿台网络设备的“互联网”。最近,这些传统硬件设备的工作越来越多地被软件所定义,即软件定义网络(SDN)。

应用数据是什么

应用数据就是网页背后的 HTTP 协议所包含的全部数据。

我们使用 Charles 反向代理软件可以轻易地得到 HTTP 协议的细节。下面我们展示一个普通的 GET 例子。使用浏览器访问 http://httpbin.org (自己尝试的时候不要选择 HTTPS 网站):

请求内容

GET / HTTP/1.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cache-Control: max-age=0
Connection: keep-alive
Host: httpbin.org
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54

数据解释:

  1. 第一行有三个元素:HTTP 方法、uri、HTTP 版本
  2. 之后的每一行均以冒号 :作为间隔符,左边是 key,右边是 value
  3. HTTP 协议中,换行采用的不是 Linux 系统的 \n,而是跟 Windows 一样的 \r\n

响应内容

HTTP/1.1 200 OK
Date: Wed, 04 Jan 2023 12:07:36 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 9593
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>httpbin.org</title>
    <link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700"
        rel="stylesheet">

    <link rel="stylesheet" type="text/css" href="/flasgger_static/swagger-ui.css">
    <link rel="icon" type="image/png" href="/static/favicon.ico" sizes="64x64 32x32 16x16" />
</head>

<body>
    <a href="https://github.com/requests/httpbin" class="github-corner" aria-label="View source on Github">
    </a>
    ... ... 此处省略一万个字
</div>
</body>

</html>

响应数据的基本规则和请求一样,第一行的三个元素分别是 协议版本、状态码、状态码的简短解释。唯一的不同是,返回值里面还有 HTTP body。

HTTP header 和 HTTP body
  1. 两个换行即 \r\n\r\n 之前的内容为 HTTP header
  2. 两个换行之后的内容为 HTTP body
  3. HTTP body 就是你在浏览器“查看源代码”所看到的内容

HTTP 下面是 TCP 层

alt
TCP 首部图示

TCP 首部重要数据描述

  1. TCP 首部中最重要的数据是 源端口目的端口
  2. 他们各由 16 位二进制数组成,2^16 = 65536,所以网络端口的范围是 0-65535
  3. 我们可以注意到,目的端口号这个重要数据是放在 TCP 首部的,和更下层的 IP 首部、以太网帧首部毫无关系

TCP 下面是 IP 层

全球所有公网 IPv4 组成了一个大型网络,这个 IP 网络其实就是互联网的本体。(IPv6 比较复杂,本文在此不做详细讨论,以下示例均基于 IPv4)

在 IP 层中,每台设备都有一个 ip 地址,形如123.123.123.123

  1. IPv4 地址范围为 0.0.0.0 - 255.255.255.255
  2. 255 为 2 的 8 次方减一,也就是说用八位二进制可以表示 0-255
  3. 四个八位即为 32 位,4 个字节

IP 首部有哪些信息

alt

从上图可以看出,IP 首部有 20 字节的固定长度是用来存储这个 IP 数据包的基本信息的:

  1. 源地址 32 位(4 个字节):123.123.123.123
  2. 目的地址 32 位(4 个字节):110.242.68.3
  3. 协议 8 位(1 个字节):内部数据包使用的协议,即 TCP、UDP 或 ICMP(就是 ping 命令使用的协议)
  4. 首部检验和 16 位(2 个字节):此 IP 首部的数据校验和,用于验证 IP 首部的数据完整性

IP 首部最重要的数据是源 ip 地址目的 ip 地址

IP 层下面是 MAC 层(物理层)

alt

物理层中的二进制数据以上图中的格式进行组织,其基本单元被称为“MAC 帧”。

每一台网络设备的 MAC 帧的长度不一定一致,默认为 1500,即 IP 层的数据会按照这个长度进行分包。在局域网速度跑不到协商速率,需要做性能优化时(例如 iSCSI 网络磁盘),可以使用“巨型帧”技术,将这个数字增加到一万,可以提升网络传输性能。不过,根据我的实际优化经验,绝大多数场景下,巨型帧对网络性能的提升小于 5%,属于一种聊胜于无的优化手段。

目的地址和源地址均为 MAC 地址,形式如 AA:BB:CC:DD:EE:FF,共有六段,每一段是一个两位的 16 进制数,两位 16 进制数换算成二进制就是 8 位,所以 MAC 地址的长度为 8*6 = 48 位。

类型字段采用 16 位二进制表示更上一层(IP 层)的网络层数据包的类型:IPv4、IPv6、ARP、iSCSI、RoCE 等等。

MAC 层就是交换机工作的地方,我们下篇文章会讲。

Nginx 的性能极限

在真实世界中,QPS 一般比保持 TCP 连接的客户端的数量要少,在此我们假设为四分之一,即:有 20 万个客户端设备在这段时间内访问我们的系统,每个客户端设备平均每 4 秒发送一个 HTTPS 请求。

单台 Nginx 反向代理的性能极限

由于 Nginx 不仅需要建立 TCP 连接,还需要将 TCP 连接中发送过来的数据包和某个进程/线程进行匹配,还需要对 HTTP 协议的信息进行解析、识别、转换、添加,所以它也有 QPS 上限:

在 2015 年主流的服务器 CPU 上,Nginx 官方在进行了极限优化的情况下进行了反向代理性能测试,在“建立 TCP 连接-发送 HTTPS 请求-断开 TCP 连接”的极限拉扯下,最高性能为 6W QPS(SSL TPS RSA 2048bit)²。

假设我们使用最新的服务器硬件,当虚拟机 CPU 达到 32 vCore 的时候,未经优化的单机 Nginx 性能就已经达到极限,能承受大约 1 万 HTTPS QPS,对应的连接用户就是 4 万,这个数字其实已经很夸张了。

TCP 负载均衡器为何能扛住五万 QPS

我们假设单台 Kong 应用网关的极限为 1 万 QPS,于是我们就需要五台 Kong,那这五台 Kong 前面的 TCP 负载均衡为何能够扛住呢?因为 TCP 负载均衡器要干的事情比 Kong 少非常多:它只需要在 IP 层做少量的工作即可。

使用负载均衡器拆分 TCP 单点

TCP 协议是一种“可靠地传输信息”的方法,它不仅有三次握手四次挥手等复杂的控制流程,还会对每一个报文段进行排序、确认、重发等操作来保证最终数据的完整和正确,所以,TCP 本身就是一种需要很多资源处理的单点,接下来我们开始拆这个单点。

TCP 负载均衡器的工作过程

我们假设客户端 ip 为 123.123.123.123,负载均衡器的 ip 为 110.242.68.3(公网)和 10.0.0.100(私网),五台 Kong 服务器的 ip 为 10.0.0.1 ~ 10.0.0.5,架构图如下:

alt

负载均衡器的工作过程如下:

1. 接收数据(左侧)

负载均衡器接收客户端数据包(报文)的过程如下:

  1. 负载均衡器收到了一个 IP 报文:源地址 123.123.123.123,目的地址 110.242.68.3
  2. IP 报文内包裹着一个 TCP 报文,详情如下:源端口 52387,目的端口 443
  3. 注意,负载均衡器只是接收了一个 IP 报文,并没有和客户端进行三次握手,并没有和客户端建立“TCP 连接”

2. 发送数据给上游服务器(右侧)

在接收到客户端的 IP 报文以后,负载均衡器会找一台上游服务器,准备把数据发送过去:

  1. 内部 TCP 报文首部:源端口 45234,目的端口 443
  2. TCP 报文外面包裹的 IP 首部:源地址 10.0.0.100,目的地址 10.0.0.1
  3. 负载均衡器将包裹着 TCP 数据包的 IP 报文发送了出去

3. 建立两个报文的映射关系并进行数据转发

负载均衡器会在内存里创建两个五元组:

左侧五元组

  1. 左侧源地址 123.123.123.123
  2. 左侧目的地址 110.242.68.3
  3. 左侧源端口 52387
  4. 左侧目的端口 443
  5. 协议 TCP

右侧五元组

  1. 右侧源地址 10.0.0.100
  2. 右侧目的地址 10.0.0.1
  3. 右侧源端口 45234
  4. 右侧目的端口 443
  5. 协议 TCP

然后,负载均衡器会关联这两个五元组:对两侧发来的数据包(报文)进行拆包和修改(两个地址+两个端口),并从另一侧发送出去。

这是什么?这就是你家的路由器(网关)呀

看过我《软件工程师需要了解的网络知识》系列文章的同学应该能一眼看出,这就是网关的工作模式,你家几百块的路由器主要干的就是这个工作。

为什么性能开销比 Kong 低

我们可以看出,负载均衡器/网关只需要做两件事:

  1. 建立两个五元组并关联
  2. 修改数据包的地址和端口,再将数据包发送出去

这个操作在网络领域内被称作 NAT(网络地址转换)。

由于这个工作非常简单,其中大部分的工作都可以用专用硬件来解决:例如开发专门的五元组存储和关联芯片,开发专门的 NPU(网络数据包处理器)来进行快速数据修改。所以,家用路由器可以做到在 300 块终端售价的情况下实现超过 1Gbit/S 的 NAT 性能。

Kong 网关需要建立“TCP 连接”

Kong 网关需要真的和客户端“建立 TCP 连接”:

  1. 三次握手建立连接
  2. 对数据包进行排序、校验,收到心跳包需要回复
  3. 需要将这个 TCP 连接和一个进程/线程进行绑定:
    1. 在收到数据以后,找出这个进程/线程,把数据发送给它
    2. 等进程/线程回复以后,再找到该进程/线程对应的那个 TCP 连接,把数据发送出去

四层负载均衡(L4)和七层负载均衡(L7)

在卖负载均衡的商业公司那里,应用网关也叫七层负载均衡,因为它工作在 OSI 七层网络模型的第七层,而我们讨论的工作在 IP 层的负载均衡叫四层负载均衡,工作在 OSI 七层网络模型的第四层。再看到 L4、L7 这两个词,你们就能一眼看穿它了,其实一点都不神秘。

还记得我们的目标吗?一百万 QPS

我们通过使用一个负载均衡器,可以完美扛下五万 QPS 的负载:一个 TCP 负载均衡器,下挂五个安装了 Kong 应用网关的虚拟机,再下挂 N 台虚拟机,无论是 PHP 还是 Golang,都可以实现五万 QPS 的设计目标。

参考资料

  1. 软件工程师需要了解的网络知识:从铜线到HTTP(三)—— TCP/IP https://lvwenhan.com/tech-epic/487.html
  2. 6W QPS(SSL TPS RSA 2048bit) https://www.nginx.com/resources/datasheets/nginx-plus-sizing-guide/

出自:https://github.com/johnlui/PPHC

本文由 mdnice 多平台发布

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux DMA 简介

文章目录 1. 前言2. 背景3. DMA 硬件基础3.1 什么是 DMA&#xff1f;3.2 为什么需要 DMA&#xff1f;3.3 DMA 传送模式3.4 DMA 常见硬件拓扑3.4.1 ARM 架构常见 DMA 硬件拓扑3.4.2 其它架构 DMA 硬件拓扑 4. Linux 下的 DMA4.1 DMA 内存地址和区域4.1.1 DMA 内存涉及的3种地址4…

Matplotlib是什么

Matplotlib 是一款用于数据可视化的 Python 软件包&#xff0c;支持跨平台运行&#xff0c;它能够根据 NumPy ndarray 数组来绘制 2D 图像&#xff0c;它使用简单、代码清晰易懂&#xff0c;深受广大技术爱好者喜爱。 NumPy 是 Python 科学计算的软件包&#xff0c;ndarray 则…

NAT转换网关实现IP地址转换,保障数据采集

NAT转换网关&#xff08;Network Address Translation Gateway&#xff09;是物通博联推出的一款物联网设备&#xff0c;用于在不同网络之间进行网络地址转换&#xff08;Network Address Translation&#xff09;&#xff0c;以实现IP地址的转换和映射。 物通博联NAT转换网关…

再谈操作系统

文章目录 ⭐1. 什么是操作系统&#x1f31f;2. 为什么要有操作系统&#x1f320;3. 操作系统如何管理 ⭐1. 什么是操作系统 先入为主&#xff0c;操作系统是一款管理软件 操作系统分为两部分 操作系统本身&#xff0c;主要做一些进程管理、内存管理、文件管理、驱动管理等工…

【AGC】删除控制台应用重建报错url is null问题

【关键字】 AGC、agconnect-services.json、InvalidParameterException 【问题描述】 有开发者反馈在删除了AppGallery Connect中某个应用及其对应的项目&#xff0c;再重新创建相同的应用&#xff08;包名一致&#xff09;&#xff0c;并且重新下载agconnect-services.json到…

【c++修行之路】IO流架构及使用

文章目录 前言输入输出库文件读写序列化与反序列化结语 前言 大家好久不见&#xff0c;今天一起来学习c中的IO流。 输入输出库 这两张架构图略显复杂&#xff0c;这里给出一张比较清楚的IO流架构图&#xff1a; 也就是说&#xff0c;我们平时使用的诸如cin、cout、cerr、cl…

2023华为产品测评官-开发者之声 | 华为云CodeArts征文活动,多重好礼邀您发声!

"2023华为产品测评官&#xff0d;开发者之声"活动激发了众多开发者和技术爱好者的热情&#xff0c;他们纷纷递交了精心编写的产品测评报告。活动社群充满活力&#xff0c;参与者们热衷于交流讨论&#xff0c;互相帮助解决问题&#xff0c;一起探索云技术的无限可能。…

C# Nullable学习

在C#1.x&#xff0c;一个值类型变量是不可以被赋予null值的&#xff0c;否则会产生异常。 在C#2.0中&#xff0c;提供了Nullable类型&#xff0c;允许用它定义包含null值&#xff08;即空值&#xff09;的数据类型&#xff0c;这对处理数据库中包含可选字段以及很多方面都有帮…

【云原生】Docker网络Overlay搭建Consul实现跨主机通信

目录 1.overlay网络是什么&#xff1f; 实现overlay环境 1.overlay网络是什么&#xff1f; 在Docker中&#xff0c;Overlay网络是一种容器网络驱动程序&#xff0c;它允许在多个Docker主机上创建一个虚拟网络&#xff0c;使得容器可以通过这个网络相互通信。 Overlay网络使用…

linux - bc 命令安装

一.引言 迁移新机器后发现没有 bc 命令&#xff0c;之前 shell 脚本的一些计算逻辑会出错&#xff0c;下面快速安装一下。 二.安装 bc 请确保在 root 权限下执行该命令&#xff1a; sudo yum install bc 出现下述界面即安装成功&#xff1a; 三.测试 bc 测试下脚本里 % 的…

Nautilus Chain 更换全新测试网,主网即将在不久上线

目前&#xff0c;Nautilus Chain 正在为主网上线前的最后阶段做准备&#xff0c;据悉该链更新了全新的测试网&#xff0c;在此前版本的测试网的基础上进行了全新的技术升级&#xff0c;最新测试网版本与生态发展的技术规划更为贴近。本次测试网升级将会是最后一次测试网版本的迭…

ylb-接口8手机号注册

总览&#xff1a; 在web模块下的service包&#xff0c;补充短信接口&#xff08;SmsService&#xff09;&#xff1a;检查用户发送的验证码是否正确 package com.bjpowernode.front.service;public interface SmsService {/*** param phone 手机号* return true&#xff1a;发…

聚集十二罗汉,探索宇宙本质,马斯克神秘的xAI

作者 | 德新编辑 | 王博 马斯克组团入局通用人工智能。 7月12日&#xff0c;马斯克发推官宣成立新的公司xAI。据官网介绍&#xff0c;这是一家试图「探索理解宇宙本质」的公司。 新公司公布了12名首批成员&#xff0c;除了马斯克外&#xff0c;他们曾经在「AlphaStar、AlphaCod…

springboot线上买菜系统

开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven…

【Linux进阶之路】冯诺依曼体系结构与操作系统

前言 存储器与CPU 在正式介绍今天的话题之前&#xff0c;博主先来带大家搞清楚一些硬件的概念&#xff0c;方便接下来的理解。 存储器&#xff0c;顾名思义就是用来存储的设备&#xff0c;那在计算机里&#xff0c;存储器包含什么呢&#xff1f; 答&#xff1a;内存 外存&a…

【C语言初阶(14)】扫雷游戏(优化:标记地雷+自动展开)

文章目录 Ⅰ游戏规则Ⅱ 游戏实现思路Ⅲ 游戏实现步骤⒈菜单界面⒉创建棋盘① 创建两个棋盘② 防止数组越界 ⒊棋盘初始化⒋棋盘的打印⒌布置地雷⒍玩家排查雷实现步骤⒎计算 x&#xff0c;y 周围有多少雷⒏展开非雷区⒐标记地雷⒑取消标记 Ⅳ 模块化代码实现⒈test.c⒉game.h⒊…

TCP协议下的三大协议的验证实验

系列文章目录 数通王国历险记&#xff08;1&#xff09; 前言 一&#xff0c;我们要先知道PDU是什么&#xff1f; 二、TCP协议下的三大协议的验证实验 1.FTP的验证实验 1&#xff0c;拓扑图 2.将lsw4配置一下 3&#xff0c;FTP服务器端开启FTP服务&#xff1a; 4&#x…

Jenkins的几种安装方式以及邮件配置

目录 Jenkins介绍 Jenkins下载、安装 一、通过war包安装 二、通过docker安装 jenkins 容器中添加 git, maven 等组件 jenkins 容器中的公钥私钥 在 jenkins 容器中调用 docker 简单的方式启动 Docker server REST API 一个 jenkins 示例 三、通过Homebrew安装 访问Je…

静态库 的制作与使用

文章目录 重要命令程序组成静态库制作流程静态库的使用 gcc main.c -o APP -I(i) 头文件路径 -l(L) 库名字&#xff08;xxx) -L 库路径 重要命令 gcc -o -I(大写i) -l(小写L) -L cp&#xff1a;复制文件 -r 递归&#xff0c;用于复制文件夹所有文件 mv&#xff1a;移动文件 程…

代码随想录算法训练营第53天 | 动态规划 part14 ● 1143.最长公共子序列 ●1035.不相交的线 ● 53. 最大子序和

# 1143.最长公共子序列 和718最长公共子数组 对比 本题可以不连续 int longestCommonSubsequence(string text1, string text2) {vector<vector<int>> dp(text1.size() 1, vector<int>(text2.size() 1, 0));for (int i 1; i < text1.size(); i) {for…