Flink调优详解:案例解析(第42天)

news2024/11/26 2:33:08

系列文章目录

一、Flink-任务参数配置
二、Flink-SQL调优
三、阿里云Flink调优

文章目录

    • 系列文章目录
    • 前言
      • 一、Flink-任务参数配置
        • 1.1 运行时参数
        • 1.2 优化器参数
        • 1.3 表参数
      • 二、Flink-SQL调优
        • 2.1 mini-batch聚合
        • 2.2 两阶段聚合
        • 2.3 分桶
        • 2.4 filter去重(了解)
      • 三、阿里云Flink调优
        • 3.1 智能调优
        • 3.2 定时调优


前言

本文主要详解常见的Flink优化策略。

官网地址:https://nightlies.apache.org/flink/flink-docs-release-1.15/docs/dev/table/config/

一、Flink-任务参数配置

1.1 运行时参数
  • 异步维度join
# 默认值:100
# 值类型:Integer
# 流批任务:流、批任务都支持
# 用处:异步 lookup join 中最大的异步 IO 执行数目
table.exec.async-lookup.buffer-capacity: 100
  • 开启微批
# 默认值:false
# 值类型:Boolean
# 流批任务:流任务支持
# 用处:MiniBatch 优化是一种专门针对 unbounded 流任务的优化(即非窗口类应用),其机制是在 `允许的延迟时间间隔内` 以及 `达到最大缓冲记录数` 时触发以减少 `状态访问` 的优化,从而节约处理时间。下面两个参数一个代表 `允许的延迟时间间隔`,另一个代表 `达到最大缓冲记录数`。
table.exec.mini-batch.enabled: false

# 默认值:0 ms
# 值类型:Duration
# 流批任务:流任务支持
# 用处:此参数设置为多少就代表 MiniBatch 机制最大允许的延迟时间。注意这个参数要配合 `table.exec.mini-batch.enabled` 为 true 时使用,而且必须大于 0 ms
table.exec.mini-batch.allow-latency: 0 ms

# 默认值:-1
# 值类型:Long
# 流批任务:流任务支持
# 用处:此参数设置为多少就代表 MiniBatch 机制最大缓冲记录数。注意这个参数要配合 `table.exec.mini-batch.enabled` 为 true 时使用,而且必须大于 0
table.exec.mini-batch.size: -1


注意: 
	1- 如果想开启微批,那么首先需要将第一个参数值设置为true;接着可以设置后面两个参数。只要程序满足后面2个参数中的任意一个条件就会触发微批处理。
	2- 微批处理能够提升程序处理数据的吞吐量,但是会导致数据的处理时效性降低
  • 并行度的设置
# 默认值:-1
# 值类型:Integer
# 流批任务:流、批任务都支持
# 用处:可以用此参数设置 Flink SQL 中算子的并行度,这个参数的优先级 `高于` StreamExecutionEnvironment 中设置的并行度优先级,如果这个值设置为 -1,则代表没有设置,会默认使用 StreamExecutionEnvironment 设置的并行度
table.exec.resource.default-parallelism: -1
  • 数据异常时的处理方式
# 默认值:ERROR
# 值类型:Enum【ERROR, DROP】
# 流批任务:流、批任务都支持
# 用处:表上的 NOT NULL 列约束强制不能将 NULL 值插入表中。Flink 支持 `ERROR`(默认)和 `DROP` 配置。默认情况下,当 NULL 值写入 NOT NULL 列时,Flink 会产生运行时异常。用户可以将行为更改为 `DROP`,直接删除此类记录,而不会引发异常。
table.exec.sink.not-null-enforcer: ERROR
  • 上游cdc去重
# 默认值:false
# 值类型:Boolean
# 流批任务:流任务
# 用处:接入了 CDC 的数据源,上游 CDC 如果产生重复的数据,可以使用此参数在 Flink 数据源算子进行去重操作,去重会引入状态开销
table.exec.source.cdc-events-duplicate: false
  • 设置空闲等待
# 默认值:0 ms
# 值类型:Duration
# 流批任务:流任务
# 用处:如果此参数设置为 60 s,当 Source 算子在 60 s 内未收到任何元素时,这个 Source 将被标记为临时空闲,此时下游任务就不依赖此 Source 的 Watermark 来推进整体的 Watermark 了。
# 默认值为 0 时,代表未启用检测源空闲。
table.exec.source.idle-timeout: 0 ms
  • 设置状态有效期
# 默认值:0 ms
# 值类型:Duration
# 流批任务:流任务
# 用处:指定空闲状态(即未更新的状态)将保留多长时间。尤其是在 unbounded 场景中很有用。默认 0 ms 为不清除空闲状态
table.exec.state.ttl: 0 ms

推荐: ttl time to live失效时间。保留窗口附近的1-3个state状态数据。举例: 例如滚动窗口大小是5秒,那么这个参数推荐设置为5000 - 15000毫秒之间

上述的参数中,常用的有:开启微批、设置状态有效期

1.2 优化器参数
  • 开启两阶段聚合
#  默认值:AUTO
#  值类型:String
#  流批任务:流、批任务都支持
#  用处:聚合阶段的策略。和 MapReduce 的 Combiner 功能类似,可以在数据 shuffle 前做一些提前的聚合,可以选择以下三种方式
#  TWO_PHASE:强制使用具有 localAggregate 和 globalAggregate 的两阶段聚合。请注意,如果聚合函数不支持优化为两个阶段,Flink 仍将使用单阶段聚合。
#  两阶段优化在计算 count,sum 时很有用,但是在计算 count distinct 时需要注意,key 的稀疏程度,如果 key 不稀疏,那么很可能两阶段优化的效果会适得其反
#  ONE_PHASE:强制使用只有 CompleteGlobalAggregate 的一个阶段聚合。
#  AUTO:聚合阶段没有特殊的执行器。选择 TWO_PHASE 或者 ONE_PHASE 取决于优化器的成本。
table.optimizer.agg-phase-strategy: AUTO

注意: 两阶段聚合必须配合微批处理的参数一起进行设置。
  • 开启分桶
#  默认值:false
#  值类型:Boolean
#  流批任务:流任务
#  用处:避免 group by 计算 count distinct\sum distinct 数据时的 group by 的 key 较少导致的数据倾斜,比如 group by 中一个 key 的 distinct 要去重 500w 数据,而另一个 key 只需要去重 3 个 key,那么就需要先需要按照 distinct 的 key 进行分桶。将此参数设置为 true 之后,下面的 table.optimizer.distinct-agg.split.bucket-num 可以用于决定分桶数是多少
#  后文会介绍具体的案例
table.optimizer.distinct-agg.split.enabled: false

#  默认值:1024
#  值类型:Integer
#  流批任务:流任务
#  用处:避免 group by 计算 count distinct 数据时的 group by 较少导致的数据倾斜。加了此参数之后,会先根据 group by key 结合 hash_code(distinct_key)进行分桶,然后再自动进行合桶。
#  后文会介绍具体的案例
table.optimizer.distinct-agg.split.bucket-num: 1024
  • 重用执行计划
#  默认值:true
#  值类型:Boolean
#  流批任务:流任务
#  用处:如果设置为 true,Flink 优化器将会尝试找出重复的自计划并重用。默认为 true 不需要改动
table.optimizer.reuse-sub-plan-enabled: true
  • source资源重用
#  默认值:true
#  值类型:Boolean
#  流批任务:流任务
#  用处:如果设置为 true,Flink 优化器会找出重复使用的 table source 并且重用。默认为 true 不需要改动
table.optimizer.reuse-source-enabled: true
  • 开启谓词下推
#  默认值:true
#  值类型:Boolean
#  流批任务:流任务
#  用处:如果设置为 true,Flink 优化器将会做谓词下推到 FilterableTableSource 中,将一些过滤条件前置,提升性能。默认为 true 不需要改动
table.optimizer.source.predicate-pushdown-enabled: true
1.3 表参数
  • 开启DML异步
#  默认值:false
#  值类型:Boolean
#  流批任务:流、批任务都支持
#  用处:DML SQL(即执行 insert into 操作)是异步执行还是同步执行。默认为异步(false),即可以同时提交多个 DML SQL 作业,如果设置为 true,则为同步,第二个 DML 将会等待第一个 DML 操作执行结束之后再执行
table.dml-sync: false
  • 设置方法的最大长度不超过64KB
#  默认值:64000
#  值类型:Integer
#  流批任务:流、批任务都支持
#  用处:Flink SQL 会通过生产 java 代码来执行具体的 SQL 逻辑,但是 jvm 限制了一个 java 方法的最大长度不能超过 64KB,但是某些场景下 Flink SQL 生产的 java 代码会超过 64KB,这时 jvm 就会直接报错。因此此参数可以用于限制生产的 java 代码的长度来避免超过 64KB,从而避免 jvm 报错。
table.generated-code.max-length: 64000
  • 本地时区
#  默认值:default
#  值类型:String
#  流批任务:流、批任务都支持
#  用处:在使用天级别的窗口时,通常会遇到时区问题。举个例子,Flink 开一天的窗口,默认是按照 UTC 零时区进行划分,那么在北京时区划分出来的一天的窗口是第一天的早上 8:00 到第二天的早上 8:00,但是实际场景中想要的效果是第一天的早上 0:00 到第二天的早上 0:00 点。因此可以将此参数设置为 GMT+08:00 来解决这个问题。
table.local-time-zone: default
  • 编译器
#  默认值:default
#  值类型:Enum【BLINK、OLD】
#  流批任务:流、批任务都支持
#  用处:Flink SQL planner,默认为 BLINK planner,也可以选择 old planner,但是推荐使用 BLINK planner
table.planner: BLINK
  • SQL方言
#  默认值:default
#  值类型:String
#  流批任务:流、批任务都支持
#  用处:Flink 解析一个 SQL 的解析器,目前有 Flink SQL 默认的解析器和 Hive SQL 解析器,其区别在于两种解析器支持的语法会有不同,比如 Hive SQL 解析器支持 between and、rlike 语法,Flink SQL 不支持
table.sql-dialect: default

二、Flink-SQL调优

2.1 mini-batch聚合

作用:微批处理能够提升程序处理数据的吞吐量,但是会导致数据的处理时效性降低

在这里插入图片描述

SQL中参数配置如下:

# 默认值:false
# 值类型:Boolean
# 流批任务:流任务支持
# 用处:MiniBatch 优化是一种专门针对 unbounded 流任务的优化(即非窗口类应用),其机制是在 `允许的延迟时间间隔内` 以及 `达到最大缓冲记录数` 时触发以减少 `状态访问` 的优化,从而节约处理时间。下面两个参数一个代表 `允许的延迟时间间隔`,另一个代表 `达到最大缓冲记录数`。
table.exec.mini-batch.enabled: false

# 默认值:0 ms
# 值类型:Duration
# 流批任务:流任务支持
# 用处:此参数设置为多少就代表 MiniBatch 机制最大允许的延迟时间。注意这个参数要配合 `table.exec.mini-batch.enabled` 为 true 时使用,而且必须大于 0 ms
table.exec.mini-batch.allow-latency: 0 ms

# 默认值:-1
# 值类型:Long
# 流批任务:流任务支持
# 用处:此参数设置为多少就代表 MiniBatch 机制最大缓冲记录数。注意这个参数要配合 `table.exec.mini-batch.enabled` 为 true 时使用,而且必须大于 0
table.exec.mini-batch.size: -1
2.2 两阶段聚合

作用:1- 提前对数据进行局部聚合操作,能够减少后续数据处理量;2-能够一定程度避免数据倾斜的问题

在这里插入图片描述

FlinkSQL中的配置:

#  默认值:AUTO
#  值类型:String
#  流批任务:流、批任务都支持
#  用处:聚合阶段的策略。和 MapReduce 的 Combiner 功能类似,可以在数据 shuffle 前做一些提前的聚合,可以选择以下三种方式
#  TWO_PHASE:强制使用具有 localAggregate 和 globalAggregate 的两阶段聚合。请注意,如果聚合函数不支持优化为两个阶段,Flink 仍将使用单阶段聚合。
#  两阶段优化在计算 count,sum 时很有用,但是在计算 count distinct 时需要注意,key 的稀疏程度,如果 key 不稀疏,那么很可能两阶段优化的效果会适得其反
#  ONE_PHASE:强制使用只有 CompleteGlobalAggregate 的一个阶段聚合。
#  AUTO:聚合阶段没有特殊的执行器。选择 TWO_PHASE 或者 ONE_PHASE 取决于优化器的成本。
table.optimizer.agg-phase-strategy: AUTO


注意: 如果想要使用两阶段聚合,那么必须同时开始mini-batch微批处理
2.3 分桶

作用:能够一定程度避免数据倾斜的问题

在这里插入图片描述

FlinkSQL的配置如下:

#  默认值:false
#  值类型:Boolean
#  流批任务:流任务
#  用处:避免 group by 计算 count distinct\sum distinct 数据时的 group by 的 key 较少导致的数据倾斜,比如 group by 中一个 key 的 distinct 要去重 500w 数据,而另一个 key 只需要去重 3 个 key,那么就需要先需要按照 distinct 的 key 进行分桶。将此参数设置为 true 之后,下面的 table.optimizer.distinct-agg.split.bucket-num 可以用于决定分桶数是多少
#  后文会介绍具体的案例
table.optimizer.distinct-agg.split.enabled: false

#  默认值:1024
#  值类型:Integer
#  流批任务:流任务
#  用处:避免 group by 计算 count distinct 数据时的 group by 较少导致的数据倾斜。加了此参数之后,会先根据 group by key 结合 hash_code(distinct_key)进行分桶,然后再自动进行合桶。
#  后文会介绍具体的案例
table.optimizer.distinct-agg.split.bucket-num: 1024
2.4 filter去重(了解)
--普通的写法
SELECT
 day,
 COUNT(DISTINCT user_id) AS total_uv,
 COUNT(DISTINCT CASE WHEN flag IN ('android', 'iphone') THEN user_id ELSE NULL END) AS app_uv,
 COUNT(DISTINCT CASE WHEN flag IN ('wap', 'other') THEN user_id ELSE NULL END) AS web_uv
FROM T
GROUP BY day


--filter优化写法
SELECT
 day,
 COUNT(DISTINCT user_id) AS total_uv,
 COUNT(DISTINCT user_id) FILTER (WHERE flag IN ('android', 'iphone')) AS app_uv,
 COUNT(DISTINCT user_id) FILTER (WHERE flag IN ('web', 'other')) AS web_uv
FROM T
GROUP BY day

filter子句能够将三个状态合并成一个共享的状态。方便程序的读取等操作。能够提升效率。

在这里插入图片描述

三、阿里云Flink调优

Flink支持智能调优和定时调优两种调优模式。

在这里插入图片描述

3.1 智能调优

简单理解,就是阿里云Flink智能来进行调优。默认会从并发度和内存来进行调优。

  • 智能调优会调整作业的并发度来满足作业流量变化所需要的吞吐。

    智能调优会监控消费源头数据的延迟变化情况、TaskManager(TM) CPU实际使用率和各个算子处理数据能力来调整作业的并发度。详情如下:

    • 作业延迟Delay指标正常(不超过60s),不修改当前作业并发。
    • 作业延迟Delay指标超过默认阈值60s,分以下两种情况来调整并发度:
      • 延迟正在下降,不进行并发度调整。
      • 延迟增加并且连续上升3分钟(默认值), 默认调整作业并发度到当前实际TPS的两倍,但不超过设置最大的资源(默认值为64 CU)。
    • 作业不存在延迟指标。
      • 作业某VERTEX节点连续6分钟实际处理数据时间占比超过80%,调大作业并发度使得SLOT使用率降低到50%,但不超过设置最大的资源(默认为64 CU)。
      • 所有TM的平均利用率连续6分钟超过80%,调高并发度使TM的CPU使用率降低到50%。
    • 所有TM的最大CPU使用率连续24小时低于20%,且VERTEX的实际处理数据时间低于20%时,调低作业的并发度使CPU和VERTEX实际处理的时间占比提高到50%。
  • 智能调优也会监控作业的内存使用和Failover情况,来调整作业的内存配置。详情如下:

    • 在JobManager GC频繁或者发生OOM异常时,会调高JM的内存,默认最大调整到16 GiB。
    • 在TM GC频繁或者发生OOM异常、HeartBeatTimeout异常时,会调高TM的内存,默认最大调整到16 GiB。
    • 在TM内存使用率超过95%时,会调大TM的内存。
    • 在TM的实际内存使用率连续24小时低于30%时,降低TM内存的配置,默认最小调整到1.6 GiB。
3.2 定时调优

定时调优计划描述了资源和时间点的对应关系,一个定时调优计划中可以包含多组资源和时间点的关系。在使用定时调优计划时,您需要明确知道各个时间段的资源使用情况,根据业务时间区间特征,设置对应的资源。

例如,某业务全天早09:00~19:00是业务高峰,19:00到第二天09:00是业务低峰。此时您可以使用定时调优功能,在高峰时间段使用30 CU,在业务低峰时使用10 CU。

说明:1 CU=1核CPU+4 GiB内存+20 GB本地存储(放置日志、系统检查点等信息)

小结:在使用阿里云调优时,可以使用一些开源的参数。

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

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

相关文章

Nvidia Isaac Sim代码编程 入门教程 2024(7)

Nvidia Isaac Sim 入门教程 2024 版权信息 Copyright 2023-2024 Herman YeAuromix. All rights reserved.This course and all of its associated content, including but not limited to text, images, videos, and any other materials, are protected by copyright law. …

mac二进制安装operator-sdk

0. 前置条件 1. 安装go 安装步骤略。 1. 下载operator-sdk源码包 https://github.com/operator-framework/operator-sdk 1.1 选择适合当前go版本的operator版本,在operator-sdk/go.mod文件中可以查看Operator-sdk使用的go版本。 2. 编译 源码包下载后&#x…

冒泡,选择,插入,希尔排序

目录 一. 冒泡排序 1. 算法思想 2. 时间复杂度与空间复杂度 3. 代码实现 二. 选择排序 1. 算法思想 2. 时间复杂度与空间复杂度 3. 代码实现 三.插入排序 1. 直接插入排序 (1). 算法思想 (2). 时间复杂度与空间复杂度 (3). 代码实现 2. 希尔排序 (1). 算法思想 …

MongoDB教程(十五):MongoDB原子操作

💝💝💝首先,欢迎各位来到我的博客,很高兴能够在这里和您见面!希望您在这里不仅可以有所收获,同时也能感受到一份轻松欢乐的氛围,祝你生活愉快! 文章目录 引言一、MongoD…

2、如何发行自己的数字代币(truffle智能合约项目实战)

2、如何发行自己的数字代币(truffle智能合约项目实战) 1-Atom IDE插件安装2-truffle tutorialtoken3-tutorialtoken源码框架分析4-安装openzeppelin代币框架(代币发布成功) 1-Atom IDE插件安装 正式介绍基于web的智能合约开发 推…

netty 自定义客户端连接池和channelpool

目录标题 客户端池化运行分析问题修复 客户端池化 通信完成之后,一般要关闭channel,释放内存。但是与一个服务器频繁的打开关闭浪费资源。 通过连接池,客户端和服务端之间可以创建多个 TCP 连接,提升消息的收发能力,同…

PyTorch张量索引

文章目录 1、简介1.1、基本概念1.2、索引类型1.3、数据准备1.4、技术摘要⭐ 2、简单行、列索引3、列表索引4、范围索引5、布尔索引6、多维索引 🍃作者介绍:双非本科大三网络工程专业在读,阿里云专家博主,专注于Java领域学习&#…

Golang | Leetcode Golang题解之第241题为运算表达式设计优先级

题目&#xff1a; 题解&#xff1a; const addition, subtraction, multiplication -1, -2, -3func diffWaysToCompute(expression string) []int {ops : []int{}for i, n : 0, len(expression); i < n; {if unicode.IsDigit(rune(expression[i])) {x : 0for ; i < n &…

大规模优化问题,Scipy?Ceres?PyTorch!

背景&#xff1a; 优化问题一般通过scipy.optimize或者Ceres Solver优化器求解。但在参数量较大的优化问题上&#xff0c;scipy提供的BFGS、L-BFGS-B、CG、SLSQP等梯度优化算法其复杂度和存储需求指数级上升&#xff0c;无法满足计算效率&#xff1b;而Ceres需要额外的语言来支…

科普文:百度交易中台之系统对账篇

百度交易中台作为集团移动生态战略的基础设施&#xff0c;面向收银交易与清分结算场景&#xff0c;赋能业务、提供高效交易生态搭建。目前支持百度体系内多个产品线&#xff0c;主要包括&#xff1a;度小店、小程序、地图打车、文心一言等。本文主要介绍了百度交易中台的交易链…

如何让主机显示Docker容器的程序界面,同时支持声音播放

系统中如果安装各种应用软件&#xff0c;很容易会因为版本冲刺引发异常。一个好的办法就是用容器来隔离系统环境&#xff0c;确保主机环境不变。对于一些有界面的程序&#xff0c;可以在容器内运行&#xff0c;让其界面显示在主机上。下面以安装和使用视频剪辑软件shotcut为例&…

【一刷《剑指Offer》】面试题 42:翻转单词顺序 VS 左旋转字符串

力扣对应题目链接&#xff1a;151. 反转字符串中的单词 - 力扣&#xff08;LeetCode&#xff09; 牛客对应题目链接&#xff1a;翻转单词序列_牛客题霸_牛客网 (nowcoder.com) 核心考点 &#xff1a;子串划分&#xff0c;子串逆置。 一、题目一 1、《剑指Offer》对应内容 2、…

Delphi5实现加密程序

效果图 平面效果图 实现“确认按钮”和“加密” //点击确认输入按钮 procedure TForm1.btn1Click(Sender: TObject); //加密部分 varpasswd_2,passwd_3:string;beginpasswd_2:edt1.Text;Delete(passwd_2,3,2);passwd_3:mima;Delete(passwd_3,3,2);if(passwd_2passwd_3) thenM…

MAE(论文阅读):Masked Autoencoders are scalable vision learners

Masked Autoencoders Are Scalable Vision Learners 研究问题&#xff1a; 本文主要介绍了掩码自编码器( MAE, Masked autoencoders)是视觉领域中可扩展的自监督学习算法。MAE具体操作为随机屏蔽输入image中的patchs&#xff0c;再重建丢失的像素。其基于两个核心操作。第…

HTML5大作业三农有机,农产品,农庄,农旅网站源码

文章目录 1.设计来源1.1 轮播图页面头部效果1.2 栏目列表页面效果1.3 页面底部导航效果 2.效果和源码2.1 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_4…

浅谈Canal原理

canal [kə’nl]&#xff0c;译意为水道/管道/沟渠&#xff0c;主要用途是基于 MySQL 数据库增量日志解析&#xff0c;提供增量数据 订阅 和 消费。应该是阿里云DTS&#xff08;Data Transfer Service&#xff09;的开源版本。 Canal与DTS提供的功能基本相似&#xff1a; 基于…

python Requests库7种主要方法及13个控制参数(实例实验)

文章目录 一、Requests库的7种主要方法二、kwargs:控制访问的13个参数 一、Requests库的7种主要方法 序号方法说明1requests.request()&#xff1a;提交一个request请求&#xff0c;作为其他请求的基础2requests.get()&#xff1a;获取HTML网页代码的方法3requests.head()&…

内网隧道——隧道技术基础

文章目录 一、正向连接与反向连接1.1 正向连接1.2 反向连接 二、端口转发三、端口映射四、端口复用五、代理和隧道的区别六、常见隧道穿透分类 环境&#xff1a; kali&#xff1a;192.168.92.6&#xff0c;MSF v6.3.25 win7&#xff1a;192.168.92.7 一、正向连接与反向连接 1…

python实现误差扩散、Floyd-Steinberg 抖动、有序抖动、Riemersma 抖动算法

误差扩散、Floyd-Steinberg 抖动、有序抖动、Riemersma 抖动算法 1.误差扩散算法详解算法步骤Floyd-Steinberg 算法公式Python 实现详细解释优缺点 2.有序抖动算法详解算法步骤Bayer矩阵公式Python 实现详细解释优缺点 3.Riemersma 抖动算法详解算法步骤公式Python 实现详细解释…

网络编程中的TCP和UDP

什么是TCP协议 TCP( Transmission control protocol )即传输控制协议&#xff0c;是一种面向连接、可靠的数据传输协议&#xff0c;它是为了在不可靠的互联网上提供可靠的端到端字节流而专门设计的一个传输协议。 面向连接 &#xff1a;数据传输之前客户端和服务器端必须建立连…