当前位置: 首页 > news >正文

TCP Analysis Flags 之 TCP Out-Of-Order

前言

默认情况下,Wireshark 的 TCP 解析器会跟踪每个 TCP 会话的状态,并在检测到问题或潜在问题时提供额外的信息。在第一次打开捕获文件时,会对每个 TCP 数据包进行一次分析,数据包按照它们在数据包列表中出现的顺序进行处理。可以通过 “Analyze TCP sequence numbers” TCP 解析首选项启用或禁用此功能。

TCP 分析展示

在数据包文件中进行 TCP 分析时,关于 “TCP Out-Of-Order” 一般是如下显示的,包括:

  1. Packet List 窗口中的 Info 信息列,以 [TCP Out-Of-Order] 黑底红字进行标注;
  2. Packet Details 窗口中的 TCP 协议树下,在 [SEQ/ACK analysis] -> [TCP Analysis Flags] 中定义该 TCP 数据包的分析说明。

考虑到 TCP 乱序、重传场景的复杂性,专家信息在乱序的判断上,前面都会有一个(suspected),表示疑似,说明并不是百分百正确,属于 Warning 级别。

TCP Out-Of-Order 定义

文档中关于 TCP Out-Of-Order 的定义看起来简单,但实际考虑到 TCP 乱序、重传场景的复杂性,在 TCP 分析中对于 TCP Out-Of-Order 是与 TCP Spurious RetransmissionTCP Fast RetransmissionTCP Retransmission 等在一起判断标记乱序或重传类型,而在不少场景还会有判断出错的问题,当然 Wireshark 考虑到这种情况,也有手动修正的选项,这正好也侧面证明了上面的说法,关于 TCP 乱序、重传的复杂性。

TCP Out-Of-Order 的定义如下,当以下所有条件都为真时设置:

  • 不是 Keep-Alive 数据包
  • TCP 段大小大于零或设置了 SYN/FIN
  • 同方向之前下一个期望的 Seq Num 大于当前数据包的 Seq Num
  • 同方向之前下一个期望的 Seq Num 和当前数据包的 Next Seq Num 不同
  • 最后一个报文段到达的时间在乱序 RTT 阈值内。这个阈值可以是两种情况之一:1). 如果在"SEQ/ACK 分析"下存在 “IRTT”(tcp.analysis.initial_rtt)字段,则使用该值作为阈值。2).如果不存在,则使用默认值 3 毫秒作为阈值。

替代 Retransmission

Set when all of the following are true:This is not a keepalive packet.
In the forward direction, the segment length is greater than zero or the SYN or FIN is set.
The next expected sequence number is greater than the current sequence number.
The next expected sequence number and the next sequence number differ.
The last segment arrived within the Out-Of-Order RTT threshold. The threshold is either the value shown in the “iRTT” (tcp.analysis.initial_rtt) field under “SEQ/ACK analysis” if it is present, or the default value of 3ms if it is not.Supersedes “Retransmission”.

具体的代码如下,总的来说这段代码是 Wireshark 中 TCP 分析模块的一部分,用于检测和标识 TCP 数据包中的各种重传/乱序类型。它的主要功能是根据当前数据包的序列号、长度、标志位以及之前收到的 TCP 数据包的信息,判断当前数据包是否属于重传/乱序,如果是则进一步确定它属于哪种重传/乱序类型。

根据分析 TCP 数据包的各种特征,对重传/乱序数据包进行分类,有助于更好地理解 TCP 连接中的重传/乱序行为,对于诊断网络问题很有帮助。这段代码的主要逻辑如下,如果所有下述条件均满足,则认为该数据包是一个乱序包(详见 case FALSE 部分)。

首先判断:

  • 检查 seq_not_advanced,序列号是否未递增;
  • 检查数据包到达的时间是否在设定的阈值内(IRTT 或 3ms);
  • 检查数据包之前是否未被看到;

继续判断:

  • 如果同方向之前下一个期望的 Seq Num 不等于当前数据包 Seq Num + Len + 1(SYN|FIN)/0,则标记为乱序;
  • 否则,如果同方向之前 LastACK 的段长度为 0(可能是纯ACK),也标记为乱序,这处理了一系列乱序包被纯 ACK 分隔的情况。
    /* RETRANSMISSION/FAST RETRANSMISSION/OUT-OF-ORDER* If the segment contains data (or is a SYN or a FIN) and* if it does not advance the sequence number, it must be one* of these three.* Only test for this if we know what the seq number should be* (tcpd->fwd->nextseq)** Note that a simple KeepAlive is not a retransmission*/if (seglen>0 || flags&(TH_SYN|TH_FIN)) {gboolean seq_not_advanced = tcpd->fwd->tcp_analyze_seq_info->nextseq&& (LT_SEQ(seq, tcpd->fwd->tcp_analyze_seq_info->nextseq));guint64 t;guint64 ooo_thres;if(tcpd->ta && (tcpd->ta->flags&TCP_A_KEEP_ALIVE) ) {goto finished_checking_retransmission_type;}/* This segment is *not* considered a retransmission/out-of-order if*  the segment length is larger than one (it really adds new data)*  the sequence number is one less than the previous nextseq and*      (the previous segment is possibly a zero window probe)** We should still try to flag Spurious Retransmissions though.*/if (seglen > 1 && tcpd->fwd->tcp_analyze_seq_info->nextseq - 1 == seq) {seq_not_advanced = FALSE;}...nextseq = seq+seglen;gboolean precedence_count = tcp_fastrt_precedence;do {switch(precedence_count) {case TRUE:...case FALSE:/* If the segment came relatively close since the segment with the highest* seen sequence number and it doesn't look like a retransmission* then it is an OUT-OF-ORDER segment.*/t=(pinfo->abs_ts.secs-tcpd->fwd->tcp_analyze_seq_info->nextseqtime.secs)*1000000000;t=t+(pinfo->abs_ts.nsecs)-tcpd->fwd->tcp_analyze_seq_info->nextseqtime.nsecs;if (tcpd->ts_first_rtt.nsecs == 0 && tcpd->ts_first_rtt.secs == 0) {ooo_thres = 3000000;} else {ooo_thres = tcpd->ts_first_rtt.nsecs + tcpd->ts_first_rtt.secs*1000000000;}/* If the segment is already seen and waiting to be acknowledged, ignore the* Fast-Retrans/OOO debate and go ahead, as it only can be an ordinary Retrans.* Fast-Retrans/Retrans are never ambiguous in the context of packets seen but* this code could be moved above.* See Issues 13284, 13843* XXX: if compared packets have different sizes, it's not handled yet*/gboolean pk_already_seen = FALSE;ual = tcpd->fwd->tcp_analyze_seq_info->segments;while(ual) {if(GE_SEQ(seq,ual->seq) && LE_SEQ(seq+seglen,ual->nextseq)) {pk_already_seen = TRUE;break;}ual=ual->next;}if(seq_not_advanced && t < ooo_thres && !pk_already_seen) {/* ordinary OOO with SEQ numbers and lengths clearly stating the situation */if( tcpd->fwd->tcp_analyze_seq_info->nextseq != (seq + seglen + (flags&(TH_SYN|TH_FIN) ? 1 : 0))) {if(!tcpd->ta) {tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);}tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;goto finished_checking_retransmission_type;}else {/* facing an OOO closing a series of disordered packets,all preceded by a pure ACK. See issue 17214 */if(tcpd->fwd->tcp_analyze_seq_info->lastacklen == 0) {if(!tcpd->ta) {tcp_analyze_get_acked_struct(pinfo->num, seq, ack, TRUE, tcpd);}tcpd->ta->flags|=TCP_A_OUT_OF_ORDER;goto finished_checking_retransmission_type;}}}precedence_count=!precedence_count;break;}} while (precedence_count!=tcp_fastrt_precedence) ;...finished_checking_retransmission_type:
  1. next expected sequence number,为 nextseq,定义为 highest seen nextseq。
  2. lastack,定义为 Last seen ack for the reverse flow。
  3. lastacklen,定义为 length of the last fwd ACK packet - 0 means pure ACK。

Packetdrill 示例

根据上述 TCP Out-Of-Order 定义和代码说明,通过 packetdrill 模拟连续传入数据分段,但顺序颠倒了一个,满足乱序的判断条件后,会标记成 TCP 乱序数据包。

# cat tcp_out_of_order_01.pkt 
0   socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0  setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0  bind(3, ..., ...) = 0
+0  listen(3, 1) = 0+0 < S 0:0(0) win 16000 <mss 1460>
+0 > S. 0:0(0) ack 1 <...>
+0.01 < . 1:1(0) ack 1 win 16000+0 accept(3, ..., ...) = 4
+0 < P. 1:21(20) ack 1 win 15000
+0.001 < P. 41:61(20) ack 1 win 15000
+0.001 < P. 21:41(20) ack 1 win 15000
# 

经 Wireshark 展示如下,可以看到满足判断条件后,No.8 标识 [TCP Out-Of-Order] ,是因为客户端发送的数据分段 No.6 Seq Num 41 和 No.4 Next Seq Num 21 之间缺少了一个长度为 20 字节的数据分段,No.6 标识为 [TCP Previous segment not captured] ,而 No.7 标识为 [TCP Dup ACK] ,紧接着之后的 No.8 Seq Num 21 + Len 20 数据包,标识为 [TCP Out-Of-Order]。

在这里再验证下,数据包到达的时间如果不在设定的阈值内,也就是 11ms 大于 IRTT 10ms,是否会被标记成乱序数据包。

# cat tcp_out_of_order_02.pkt 
0   socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+0  setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0  bind(3, ..., ...) = 0
+0  listen(3, 1) = 0+0 < S 0:0(0) win 16000 <mss 1460>
+0 > S. 0:0(0) ack 1 <...>
+0.01 < . 1:1(0) ack 1 win 16000+0 accept(3, ..., ...) = 4
+0 < P. 1:21(20) ack 1 win 15000
+0.001 < P. 41:61(20) ack 1 win 15000
+0.011 < P. 21:41(20) ack 1 win 15000
# 

答案是不会,不满足乱序数据包条件,被标记成了重传数据包。

实例

关于 TCP Out-Of-Order 的实例,实际日常抓包中经常会看到,是比较常见的一种 TCP 分析信息,而在各类场景中,也会伴生着出现像是 TCP Dup ACKTCP Previous segment not captured 等信息。

  1. 标准 TCP 乱序

标准的 TCP 乱序场景,No.119 和 No.120 中间缺失一个 Seq 237 + Len 207 的数据分段,No.120 首先会提示 [TCP Previous segment not captured],之后 No.122 Seq 237 + Len 207 的数据包到来,满足乱序数据包的判断条件,标记成 [TCP Out-Of-Order]

也可以使用 ip.id 加以佐证,如下,No.122 IP ID 15284,实际上是在 No.119 15283 和 No.120 15286 之间,说明就是乱序数据包。

ip.id 辅助的方式非标准实现,多数场景下可用,但不是所有场景都适合。

  1. TCP 乱序(纯 ACK)

代码中描述的一系列乱序包被纯 ACK 分隔的场景,其中 No.13 为纯 ACK,No.15 为乱序的第一个数据包,它满足判断乱序代码中继续判断的第一种场景,nextseq != (seq + seglen),因此被标记为 [TCP Out-Of-Order],而 No.19 为乱序的第二个数据包,它满足判断乱序代码中继续判断的第二种场景,lastacklen = 0,因为 No.13 为纯 ACK,所以 No.19 也被标记为 [TCP Out-Of-Order]

  1. TCP 快速重传还是 TCP 乱序

TCP 快速重传和乱序混淆,这似乎在目前的 Wireshark 版本中是经常可以看到的一种场景,如下案例:

  1. 服务器所发的数据包 No.20 前丢了一个 TCP 分段 Seq 9577 ,所以 No.20 标记为 TCP Previous segment not captured
  2. 客户端回应第一个 No.21 DUP ACK 确认还要 Seq 9577 分段(原 ACK 在 No.19);
  3. 服务器下一个数据包 No.22 仍不是 TCP 分段 Seq 9577;
  4. 因此客户端回应第二个 No.23 DUP ACK 确认继续要 Seq 9577 分段;
  5. 此时服务器像是因为 DUP ACK 的原因触发了快速重传,发送了 No.24 Seq 9577 数据包。

Wireshark 在此判断 No.24 为快速重传感觉确实合情合理,因为包括 DUP ACK >=2 等条件综合判断为真时就会认为是快速重传。但是细细一琢磨,会发现里面有些问题:IRTT,IRTT 为 0.103362s ,说明客户端和服务器端 RTT 约为 103ms,如果捕获点在客户端,No.24 和 No.23 之间的时间差值仅为 71ns。试问从客户端发出 No.23 到服务器收到 No.23 之后触发快速重传,再到客户端所捕获,这个 71ns 的时间完全不符合现实。

此时通过 IP.ID 加以佐证,No.24 的 IP ID 为 49749 ,在 No.20 和 No.22 之前,因此 No.24 实际上是乱序,而不是快速重传。

总结

考虑到数据包会出现乱序、重传等各类不同的场景,产生 TCP Out-Of-Order 的情形自然也是五花八门,具体问题具体分析。

相关文章:

TCP Analysis Flags 之 TCP Out-Of-Order

前言 默认情况下&#xff0c;Wireshark 的 TCP 解析器会跟踪每个 TCP 会话的状态&#xff0c;并在检测到问题或潜在问题时提供额外的信息。在第一次打开捕获文件时&#xff0c;会对每个 TCP 数据包进行一次分析&#xff0c;数据包按照它们在数据包列表中出现的顺序进行处理。可…...

【MyBatis 核心工作机制】注解式开发与动态代理原理

有很多朋友可能已经在开发中熟练使用 MyBatis 或者刚开始学习 MyBatis&#xff0c;对于它的一些工作机制不太了解。“咦&#xff0c;怎么写几个注解&#xff0c;写几个配置文件&#xff0c;就能实现这些效果呢&#xff0c;好神奇呀&#xff01;”当你看完这篇博客之后&#xf…...

深度学习在图像识别中的最新进展与实践案例

深度学习在图像识别中的最新进展与实践案例 在当今信息爆炸的时代&#xff0c;图像作为信息传递的重要载体&#xff0c;其处理与分析技术显得尤为重要。深度学习&#xff0c;作为人工智能领域的一个分支&#xff0c;凭借其强大的特征提取与模式识别能力&#xff0c;在图像识别…...

vue3中如何自定义插件

英译汉插件 i18n.ts export default {install: (app: any, options: any) > {// 注入一个全局可用的$translate()方法app.config.globalProperties.$translate (key: string) > {// 获取options对象的深层属性// 使用key作为索引return key.split(".").redu…...

【机器学习】回归

文章目录 1. 如何训练回归问题2. 泛化能力3. 误差来源4. 正则化5. 交叉验证 1. 如何训练回归问题 第一步&#xff1a;定义模型 线性模型&#xff1a; y ^ b ∑ j w j x j \hat{y} b \sum_{j} w_j x_j y^​b∑j​wj​xj​ 其中&#xff0c;( w ) 是权重&#xff0c;( b )…...

Maven项目中不修改 pom.xml 状况下直接运行OpenRewrite的配方

在Java 的Maven项目中&#xff0c;可以在pom.xml 中配置插件用来运行OpenRewrite的Recipe&#xff0c;但是有一些场景是希望不修改pom.xml 文件就可以运行Recipe&#xff0c;比如&#xff1a; 因为不需要经常运行 OpenRewrite&#xff0c;所以不想在pom.xml 加入不常使用的插件…...

【翻译】Sora 系统卡-12月9日

Sora System ard | OpenAI 简介 Sora 概述 Sora 是 OpenAI 的视频生成模型&#xff0c;旨在接收文本、图像和视频输入并生成新视频作为输出。用户可以创建各种格式的分辨率高达 1080p&#xff08;最长 20 秒&#xff09;的视频&#xff0c;从文本生成新内容&#xff0c;或增强…...

如何在 Spring Boot 微服务中设置和管理多个数据库

在现代微服务架构中&#xff0c;通常需要与多个数据库交互的服务。这可能是由于各种原因&#xff0c;例如遗留系统集成、不同类型的数据存储需求&#xff0c;或者仅仅是为了优化性能。Spring Boot 具有灵活的配置和强大的数据访问库&#xff0c;可以轻松配置多个数据库。在本综…...

Ubuntu20.04安装Foxit Reader 福昕阅读器

Ubuntu20.04安装Foxit Reader 福昕阅读器 文章目录 Ubuntu20.04安装Foxit Reader 福昕阅读器 先更新一下源 sudo apt update sudo apt upgrade下载Foxit Reader的稳定版本 wget https://cdn01.foxitsoftware.com/pub/foxit/reader/desktop/linux/2.x/2.4/en_us/FoxitReader.e…...

学习threejs,THREE.CircleGeometry 二维平面圆形几何体

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.CircleGeometry 圆形…...

Tonghttpserver6.0.1.3 使用整理(by lqw)

文章目录 1.声明2.关于单机版控制台和集中管理控制台3.单机版控制台3.1安装&#xff0c;启动和查看授权信息3.2一些常见的使用问题&#xff08;单机控制台&#xff09;3.3之前使用的是nginx&#xff0c;现在要配nginx.conf上的配置&#xff0c;在THS上如何配置3.4如何配置密码过…...

redis开发与运维-redis0401-补充-redis流水线与Jedis执行流水线

文章目录 【README】【1】redis流水线Pipeline【1.1】redis流水线概念【1.2】redis流水线性能测试【1.2.1】使用流水线与未使用流水线的性能对比【1.2.2】使用流水线与redis原生批量命令的性能对比【1.2.3】流水线缺点 【1.3】Jedis客户端执行流水线【1.3.1】Jedis客户端执行流…...

OPPO Java面试题及参考答案

Java 语言的特点 Java 是一种面向对象的编程语言,它具有以下显著特点。 首先是简单性。Java 的语法相对简单,它摒弃了 C 和 C++ 语言中一些复杂的特性,比如指针操作。这使得程序员能够更专注于业务逻辑的实现,而不是陷入复杂的语法细节中。例如,Java 的内存管理是自动进行…...

Ubuntu 22.04 升级 24.04 问题记录

一台闲置笔记本使用的 ubuntu 还是 18.04&#xff0c;最近重新使用&#xff0c;发现版本过低&#xff0c;决定升级&#xff0c;于是完成了 18.04 -> 20.04 -> 22. 04 -> 24.04 的三连跳。 一、升级过程中黑屏 主要问题是在 22.04 升级到 24.04 过程中出现了黑屏仅剩…...

Java重要面试名词整理(五):Redis

文章目录 Redis高级命令Redis持久化RDB快照&#xff08;snapshot&#xff09;**AOF&#xff08;append-only file&#xff09;****Redis 4.0 混合持久化** 管道&#xff08;Pipeline&#xff09;**StringRedisTemplate与RedisTemplate详解**Redis集群方案gossip脑裂 Redis LuaR…...

单元测试中创建多个线程测试 ThreadLocal

单元测试中创建多个线程测试 ThreadLocal 在单元测试中&#xff0c;可以通过以下方式创建多个线程来测试 ThreadLocal 的行为。 目标 验证 ThreadLocal 在多线程环境下是否能正确隔离每个线程的数据。 实现步骤 定义需要测试的类 包含 ThreadLocal 对象的类&#xff0c;提供…...

iDP3复现代码数据预处理全流程(二)——vis_dataset.py

vis_dataset.py 主要作用在于点云数据的可视化&#xff0c;并可以做一些简单的预处理 关键参数基本都在 vis_dataset.sh 中定义了&#xff0c;需要改动的仅以下两点&#xff1a; 1. 点云图像保存位置&#xff0c;因为 dataset_path 被设置为了绝对路径&#xff0c;因此需要相…...

容器化部署服务全流程

系列文章目录 文章目录 系列文章目录前言一、什么是容器&#xff1f;二、如何安装docker三、如何写dockerfile四、如何启动服务五、常见命令总结总结 前言 这篇文章&#xff0c;‌主要目的是通过容器化技术简化应用程序的部署、运行和管理&#xff0c;提高开发、测试和生产环境…...

Flutter DragTarget拖拽控件详解

文章目录 1. DragTarget 控件的构造函数主要参数&#xff1a; 2. DragTarget 的工作原理3. 常见用法示例 1&#xff1a;实现一个简单的拖拽目标解释&#xff1a;示例 2&#xff1a;与 Draggable 结合使用解释&#xff1a; 4. DragTarget 的回调详解5. 总结 DragTarget 是 Flutt…...

操作系统动态分区分配算法-首次适应算法c语言实现

目录 一、算法原理 二、算法特点 1.优先利用低址空闲分区&#xff1a; 2.查找开销&#xff1a; 3.内存碎片&#xff1a; 三、内存回收四种情况 1.回收区上面&#xff08;或后面&#xff09;的分区是空闲分区&#xff1a; 2.回收区下面&#xff08;或前面&#xff09;的…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...

C++ 设计模式 《小明的奶茶加料风波》

&#x1f468;‍&#x1f393; 模式名称&#xff1a;装饰器模式&#xff08;Decorator Pattern&#xff09; &#x1f466; 小明最近上线了校园奶茶配送功能&#xff0c;业务火爆&#xff0c;大家都在加料&#xff1a; 有的同学要加波霸 &#x1f7e4;&#xff0c;有的要加椰果…...

Qt的学习(一)

1.什么是Qt Qt特指用来进行桌面应用开发&#xff08;电脑上写的程序&#xff09;涉及到的一套技术Qt无法开发网页前端&#xff0c;也不能开发移动应用。 客户端开发的重要任务&#xff1a;编写和用户交互的界面。一般来说和用户交互的界面&#xff0c;有两种典型风格&…...

循环语句之while

While语句包括一个循环条件和一段代码块&#xff0c;只要条件为真&#xff0c;就不断 循环执行代码块。 1 2 3 while (条件) { 语句 ; } var i 0; while (i < 100) {console.log(i 当前为&#xff1a; i); i i 1; } 下面的例子是一个无限循环&#xff0c;因…...

Vuex:Vue.js 应用程序的状态管理模式

什么是Vuex&#xff1f; Vuex 是专门为 Vue.js 应用程序开发的状态管理模式 库。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。 在大型单页应用中&#xff0c;当多个组件共享状态时&#xff0c;简单的单向数据流…...

NLP常用工具包

✨做一次按NLP项目常见工具的使用拆解 1. tokenizer from torchtext.data.utils import get_tokenizertokenizer get_tokenizer(basic_english) text_sample "Were going on an adventure! The weather is really nice today." tokens tokenizer(text_sample) p…...

IDEA中微服务指定端口启动

在使用IDEA开发SpringBoot微服务时&#xff0c;经常需要开启多个服务实例以测试负载均衡&#xff0c;以下几种方法开启不同端口。 直接在配置文件中指定 # application.propertiesserver.port8001指定VM参数 点击Modify options&#xff0c;选择Add VM options&#xff0c;值…...

一、ES6-let声明变量【解刨分析最详细】

一、块级作用域 { let Tim"Tim是靓仔&#xff01;" } console.log("Tim:",Tim) 打印结果&#xff1a;Tim未进行任何定义&#xff01; 原因&#xff1a;因为Tim定义再块级{}里面&#xff0c;它的声音Tim只服务于该块级里面。而打印结果是再块级外面&#…...