为什么 Linux 内核协议栈会丢弃 SYN 数据包

news2024/11/25 10:09:20

最近了解到 SYN 数据包丢弃的问题,网上有一些资料,这里记录分享一下。

serverfault上的重要信息

tcp - No SYN-ACK Packet from server - Server Fault

信息如下:

        My embedded system with LwIP is the client and I have server1 and server2. I connected to server1 and end the connection before connecting to server2.

Further breakdown on the flow:

  1. Client creates New Socket with server1
  2. Client sent DNS packet to obtain server1's ip address; received ACK from AP
  3. Client send TCP SYN packet;
  4. Server1 send TCP SYN-ACK and perform some data transmission
  5. Client ends connection with server1 by sending TCP RST packet; and close socket
  6. Client creates New Socket with server2
  7. Client sent DNS packet to obtain server2's ip address; received ACK from AP
  8. Client send TCP SYN packet to server2
  9. Server2 send TCP SYN-ACK and perform some data transmission
  10. Client ends connection with server2 by sending TCP RST packet; and close socket

        However, sometimes server2 did not response to client's SYN Packet which is in Step 9. Its only happens sometime. I checked several forum like:

[1] Why would a server not send a SYN/ACK packet in response to a SYN packet

[2] Server not sending a SYN/ACK packet in response to a SYN packet

主要就是关闭下面配置:

sysctl -w net.ipv4.tcp_timestamps=0
sysctl -w net.ipv4.tcp_tw_recycle=0

或设置

cat /etc/sysctl.conf 

net.ipv4.tcp_tw_recycle = 0
net.ipv4.tcp_tw_reuse = 0
net.ipv4.tcp_window_scaling = 0
net.ipv4.tcp_timestamps = 0

下面翻译自:Why Are Linux Kernel Protocol Stacks Dropping SYN Packets - Alibaba Cloud Community

SYN 数据包丢弃

        在排除网络问题时,经常会遇到 TCP 连接失败的情况。如果能获取到两端抓到的数据包,则数据包如下:

  • 客户端一直在以指数退避方式重新传输 TCP SYN。

这是因为第一个数据包还没有获得RTT和RTO,会在1、2、4、8秒左右重传,直到net.ipv4.tcp_syn_retries重传完成。

  • 在服务器端可以看到TCP SYN包已经到达网卡,但是没有返回TCP包。

        这个问题出现的比较频繁。本博客将重点讨论与 TCP 协议栈相关的网络问题。对于TCP协议栈来说,我们指的是相关的网络问题可能是这样的情况:TCP SYN包可能已经到达了内核的TCP处理模块,但是根据服务器端内核代码却没有给客户端返回SYNACK。客户端持续重传TCP SYN也可能是由其他原因造成的,比如服务器端多个网卡导致访问路径不一致,或者SYN报文被规则拦截iptables,但这里不讨论这些。相反,我们将关注最常见的原因。

处于监听状态时处理 TCP SYN

        在本教程中,我们将使用广泛使用的CentOS 7内核版本。在本教程中,我们首先看一下TCP处理SYN的主要逻辑,并根据案例处理经验分析可能出现问题的点。Listen状态下的socket处理第一个TCP SYN报文的逻辑如下:

tcp_v4_do_rcv() @net/ipv4/tcp_ipv4.c
        |--> tcp_rcv_state_process() @net/ipv4/tcp_input.c // This functiuon implements the processing of accept messgaes in the vast TCP state (except for ESTABLISHED and TIME-WAIT), including of course the LISTEN state we are interested in.
                |--> tcp_v4_conn_request() @@net/ipv4/tcp_ipv4.c // When the TCP socket is in the LISTEN state and the TCP SYN flag is in the received message is set, it comes to this function.

        CentOS中的内核代码可能会略有调整。如果您需要跟踪源代码中的确切行数,systemtap是一种适合此目的的方法,如下所示:

# uname -r
3.10.0-693.2.2.el7.x86_64
# stap -l 'kernel.function("tcp_v4_conn_request")'
kernel.function("tcp_v4_conn_request@net/ipv4/tcp_ipv4.c:1303")

在tcp_v4_conn_request()的代码中,前几行函数逻辑如下:

1

        进入该函数的前提是TCP套接字处于Listen状态,并且接收到的数据包中设置了TCP SYN标志。进入函数逻辑后,我们可以发现函数应该考虑各种可能出现的异常,但很多异常其实并不那么常见。比如前几行的两种情况:

  1. 第1482行:拒绝发送到广播和组播的数据包。
  2. 1490行:如果请求队列(存放SYN包的队列)已满,则isn为0,为want_cookiefalse,则丢弃SYN包。

        第一种情况比较容易理解,实际中还没有见过。但是,第二种情况稍微复杂一些,在实际中也有一定概率会遇到。下面我们就来看看:

        第一个条件,请求队列已满,其实很容易满足。syn 洪水攻击很容易导致这种情况发生。TCP_SKB_CB(skb)->isn 的分配与函数开头的when相同。这是用于计算 TCP 控制块结构中的 RTT 的字段。表示want_cookie是否使用syn syncookies方法。它在tcp_syn_flood_action()中的定义如下。如果ifdef前面添加CONFIG_SYN_COOKIES,并且内核参数net.ipv4.tcp_syncookies也设置为1,则摘要返回 true,因此want_cookie返回为true

2

        因此,在上述丢弃SYN数据包的情况下,真正的前提条件是内核参数net.ipv4.tcp_syncookies未启用。但在实际生产系统中,参数net.ipv4.tcp_syncookies是默认启用的。Syn syncookies是一种通过以时间(CPU计算)换取空间(请求队列)来防御syn Flood攻击的方法。在实际生产中,任何场景都不需要显式关闭该开关。所以一般来说,1490行的请求并不是很常见。

内核丢弃SYN数据包的主要场景

        下面介绍两种主要可能导致SYN包丢失的场景以及如何快速判断服务器不返回SYNACK的原因。

1. 每主机 PAWS(Protect Against Wrapped Sequences ) 检查导致 SYN 数据包丢失

症状

        这是实际生产环境中最常见的问题:对于同时启用了net.ipv4.tcp_tw_recycle和 的服务器net.ipv4.tcp_timestamps,当服务器有 NAT 客户端访问时,出现此问题的概率非常高。从客户端来看,这个问题的症状是新连接不稳定。有时可以连接,有时不能连接。

每主机 PAWS 原则

        有关背景信息,PAWS 是 Protect Against Wrapped Sequences 的缩写,这是一种防止序列号被包装的方法。接下来,Per-host 检查对等主机的 IP 地址,而不是 IP 端口的四元组。

        每主机PAWS检查的方式如下:对于快速回收的TIME_WAIT套接字的五元组对等主机IP,这有助于防止来自同一主机的旧数据的干扰。因此,新 SYN 数据包的 TCP Timestamps 选项需要在 60 秒内增加。当客户端处于NAT环境中时,这个条件往往不容易满足。

        理论上,只需要记住上面这句话,就可以解决很多客户端三向握手时而连通、时而断开的问题。欲了解更多信息,请参阅下面的详细解释。

为什么存在单主机 PAWS?

RFC 1323中提到了每主机 PAWS ,如下:

  • 允许旧的重复段过期。为了取代 TIME-WAIT 状态的这一功能,必须有一种跨连接操作的机制。PAWS 严格定义在单个连接内;最后一个时间戳是 TS.Recent 保存在连接控制块中,并在连接关闭时丢弃。
  • 可以向 TCP 添加一个附加机制,即从任何连接接收到的最后时间戳的每主机缓存。然后,如果可以保证时间戳时钟自旧连接打开以来至少已滴答一次,则可以在 PAWS 机制中使用该值来拒绝连接早期版本中的旧重复段。这要求 TIME-WAIT 延迟加上 RTT 必须至少是发送方时间戳时钟的一个刻度。此类扩展不属于本 RFC 提案的一部分。
  • 请注意,这是 Garlick、Rom 和 Postel [Garlick77] 提出的机制的一个变体,该机制要求每个主机维护包含每个连接上的最高序列号的连接记录。如果使用时间戳,则只需为每个远程主机保留一个数量,而不管到该主机的同时连接数是多少。

需要TIME_WAIT的原因在.的代码注释tcp_minisocks.c中也有解释。而PAWS机制,TIME_WAIT快速回收的理论基础如下:

  • TIME-WAIT 状态的主要目的是,当其中一端处于 LAST-ACK 或 CLOSING 重传 FIN(可能还有数据尾部)并且一个或多个 ACK​​ 丢失时,优雅地关闭连接。
  • 什么是TIME-WAIT超时?它与互联网中的最大数据包生存期相关,这会导致错误的结论,即它被设置为捕获偏离其路径的“旧重复段”。这并不完全正确。该超时的计算方式使其超过最大重传超时,足以允许丢失由对等方发送的一个(或多个)分段和我们的 ACK。这个时间可以根据RTO来计算。
  • 当TIME-WAIT套接字收到RST时,意味着另一端终于关闭了,我们也可以杀死TIME-WAIT。
  • TIME-WAIT 的第二个目的是捕获旧的重复段。好吧,这当然是纯粹的偏执,但如果我们用这种语义加载 TIME-WAIT,我们就不能用 RST 杀死 TIME-WAIT 状态。
  • 如果我们发明一些更聪明的方法来捕获重复项(基于 PAWS),我们可以将 TIME-WAIT 截断为多个 RTO。

        根据上面RFC的描述以及内核代码注释,我们可以看出Linux内核对状态实现了快速回收机制TIME-WAIT。Linux可以丢弃60秒的TIME-WAIT时间,直接缩短到RTO时间的3.5倍,因为Linux使用了一些“聪明”的方法来捕获旧的重复数据包(例如,基于PAWS机制)。相比之下,Linux 确实使用每主机 PAWS 来防止先前连接中的数据包被包装到新连接中。

Linux 内核实现

        在tcp_ipv4.c中,在收到 SYN 之前,如果满足以下两个条件,则检查对等体是否经过验证,即执行每主机 PAWS 检查:

  • 接收到的数据包具有 TCP 时间戳选项。
  • 计算机上启用了内核参数net.ipv4.tcp_tw_recycle。
...
else if (!isn) {
/* VJ's idea. We save last timestamp seen
 * from the destination in peer table, when entering
 * state TIME-WAIT, and check against it before
 * accepting new connection request.
 *
 * If "isn" is not zero, this request hit alive
 * timewait bucket, so that all the necessary checks
 * are made in the function processing timewait state.
 */
if (tmp_opt.saw_tstamp &&  // The report contains TCP timestamp option
    tcp_death_row.sysctl_tw_recycle &&  // The net.ipv4.tcp_tw_recyclekernel parameter is enabled.
    (dst = inet_csk_route_req(sk, &fl4, req)) != NULL &&
    fl4.daddr == saddr) {
    if (!tcp_peer_is_proven(req, dst, true)) {  // peer  (per-host PAWS)
        NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
        goto drop_and_release;
    }
}

        在tcp_metrics.c中,Linux per-host PAWS 的实现逻辑如下。简单来说,正如本节开头提到的:新的SYN数据包的TCP Timestamps选项需要在60秒内增加。

bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool paws_check)
{
    struct tcp_metrics_block *tm;
    bool ret;
    ...
    
    tm = __tcp_get_metrics_req(req, dst);
    if (paws_check) {
      if (tm &&
          // peer information is saved within 60 seconds (TCP_PAWS_MSL)之内
          (u32)get_seconds() - tm->tcpm_ts_stamp < TCP_PAWS_MSL &&
          // Compared with the timestamp in the current(TCP_PAWS_WINDOW)
          (s32)(tm->tcpm_ts - req->ts_recent) > TCP_PAWS_WINDOW)
        ret = false;
      else
        ret = true;
    }
}

NAT 环境中对客户端的影响

        当这种允许TIME-WAIT状态快速回收的每主机PAWS机制在Linux中实现时,它被设计为基于具有足够数量的IPv4地址池的网络环境的解决方案。然而,随着互联网的快速发展,NAT的应用越来越普遍,客户端在SNAT设备内访问同一台服务器的情况也很常见。

        Per-host PAWS 机制通过 TCP Timestamps 选项字段的增加来确定包装的数据,而时间戳是根据每个客户端的 CPU 滴答数获得的值,可以说在 NAT 设备内是完全随机的。当客户端主机1通过NAT与服务器建立TCP连接,然后服务器关闭并快速回收TIME-WAIT套接字时,其他客户端主机的新连接源IP与服务器对等表中记录的相同,但TCP Timestamps选项是完全随机的或者与主机1当时记录的时间戳相比有50%的概率是随机的。如果时间戳小于主机1的时间戳,则60秒内新连接将被拒绝,60秒后新连接将成功。如果时间戳大于主机1的时间戳,则新连接直接成功。所以,从客户端来看,这个问题的症状就是新连接不稳定。有时可以连接,有时不能连接

        这就是NAT环境下客户端使用TIME-WAIT快速回收机制带来的副作用。这种副作用在每主机 PAWS 机制设计之初就无法预料到,因为当时的网络环境与现在有很大不同。在当前的网络环境下,唯一的建议是禁用TIME-WAIT快速回收,即制作net.ipv4.tcp_tw_recycle=0. 禁用net. ipv4.tcp_timestamps删除 TCP 时间戳选项也可以解决此问题。但由于时间戳是计算RTT和RTO的基础,因此一般不建议禁用。

故障排除

        在实际生产中,排除故障并不容易。但对于同时启用了net.ipv4.tcp_tw_recycle和 的net.ipv4.tcp_timestamps服务器,当服务器有 NAT 客户端访问时,出现此问题的概率非常高,所以如果获取了这两个内核参数的设置以及客户端网络的 NAT 环境,就可以做出基本的判断。

        另外,您可以参考 中的统计数据netstat -s,该统计数据来自/proc/net/snmp/proc/net/netstat/proc/net/sctp/snmp。如下所示,该统计值表示有多少新连接因时间戳而被拒绝。这是历史统计总计,因此两个时间点之间的差异对于故障排除更有意义。

xx passive connections rejected because of time stamp

2. 接受队列已满导致 SYN 数据包丢失

症状

        不存在统一的、有规律的现象。当 TCP 接受队列已满时会发生这种情况。当用户空间应用程序出现问题时,通常会发生这种情况。一般来说,发生的概率不是很高。

原则

        接受队列翻译为全连接队列或者接收队列。新连接经过三次握手后进入接受队列。用户空间应用程序调用accept系统调用来获取连接并创建一个新的套接字,返回与该套接字关联的文件描述符(fd)。在用户空间,可以使用poll等机制,通过可读事件获知已经完成3次握手的新连接已进入accept队列,收到通知后可以立即调用accept系统调用来获取新连接。

        接受队列的长度是有限的。长度取决于 min [backlog, net.core.somaxconn],它是两个参数中较小的一个。

  • Backlog是应用程序调用Listen系统调用时的第二个参数。请参考#include 中的 int Listen(int sockfd, int backlog) 。
  • Net.core.somaxconn 是系统内核参数。默认值为128。当应用程序监听时,如果设置的backlog较大(例如NGINX默认为512),并且全局内核参数没有调整,则accept队列的长度仍然会由较小的net.core.somaxconn决定。

        即使在并发连接数较多的情况下,应用程序正常使用accept系统调用获取accept队列中的连接也不会因为效率问题而被延迟。但是,如果由于应用程序阻塞而未能及时获得连接,则可能会导致接受队列已满,从而导致新的 SYN 数据包被丢弃。

Linux 内核实现

        在tcp_ipv4中,“当接受队列已满时拒绝 SYN 数据包”的实现非常简单,如下:

/* Accept backlog is full. If we have already queued enough
 * of warm entries in syn queue, drop request. It is better than
 * clogging syn queue with openreqs with exponentially increasing
 * timeout.
 */
//If accept queueis full, and SYN queuehas a semi-join that has not been retransmitted by SYNACK, the SYN request is discarded.
if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) {
  NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
  goto drop;
}

在sock.h中,定义了完整接受队列的内联函数:

static inline bool sk_acceptq_is_full(const struct sock *sk)
{
    return sk->sk_ack_backlog > sk->sk_max_ack_backlog;
}

inet_connection_sock.h和request_sock.h中定义了判断SYN队列中是否存在未重传SYNACK的半连接的方法:

static inline int inet_csk_reqsk_queue_young(const struct sock *sk)
{
    return reqsk_queue_len_young(&inet_csk(sk)->icsk_accept_queue);
}

static inline int reqsk_queue_len_young(const struct request_sock_queue *queue)
{
    return queue->listen_opt->qlen_young;
}

        以上是3.10中的实现。其实我们需要判断两个条件:“accept队列是否已满”和“SYN队列是否有没有SYNACK重传的半连接”。当接受队列已满时,通常会存在大量新连接,因此通常会同时满足第二个条件。如果SYN队列没有半连接,即当接受队列满时还没有重传SYNACK,Linux内核仍然接受SYN并返回SYNACK。这种情况在实际生产中很少见,除非应用程序进程完全停止,例如使用SIGSTOP信号停止进程。所以当accept队列满时,TCP内核协议栈仍然不会直接丢弃SYN数据包。

        由于接受队列已满而丢弃 SYN 的逻辑在较新的内核版本中略有变化。例如4.10中,判断条件由2个变为1个,即内核只判断accept队列是否已满。因此,在这些版本中,当接受队列已满时,内核将直接丢弃SYN数据包。

故障排除

        当用户空间应用程序出现问题时,通常会发生这种问题。一般来说,发生的概率不是很高。可以通过以下两种方法来确认该问题:

使用ss命令查看实时问题

        使用 ss 命令的选项 -l 检查监听套接字。显示 Recv-Q 和 Send-Q。Recv-Q表示当前accept队列的总连接数,Send-Q表示accept队列的最大长度。如下所示: 几个进程默认的accept队列是128,因为受到net.core.somaxconn=128系统的限制。

3

Netstat -s 统计

        参考netstat -s 中的统计信息。下面的统计值表示由于套接字溢出而被拒绝的新连接数。同样,这也是一个历史统计总计,两个时间点之间的差异对于故障排除更有意义。

xx times the listen queue of a socket overflowed

建议的解决方案

        如果确认SYN包被丢弃是由于accept队列的原因,那么很自然地想到解决办法就是增加accept队列的长度。同时增加backlog和net.core.somaxconn参数可以增加accept队列的长度。

        但一般来说,这种方法只能缓解问题,最有可能的情况是加长的accept队列很快又被填满。因此,解决这个问题的最好方法是检查应用程序,看看为什么它接受新连接的速度这么慢,解决根本原因。

概括

        本博客文章的主体总结了两个主要场景,主要是与云基础设施和服务软件层相关的问题,其中 SYN 由于每主机 PAWS 检查和完整接受队列而被丢弃。这两种情况涵盖了绝大多数 TCP 堆栈丢弃 SYN 的情况。如果其他协议栈出现SYN丢包,则需要结合参数配置和代码逻辑进一步具体排查。

参考

tcp - No SYN-ACK Packet from server - Server Fault

Why Are Linux Kernel Protocol Stacks Dropping SYN Packets - Alibaba Cloud Community

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

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

相关文章

微信小程序开发,小程序类目符合,线上版本无权限申请wx.getLocation接口

我开发 的小程序类目符合wx.getLocation接口的申请标准 但是却还是显示无权限申请 后来研究好久才发现&#xff0c;小程序需要在发布线上版本时提交用户隐私保护指引 如未设置也可以在 设置-服务内容声明-用户隐私保护指引-声明处理用户信息项并补充填写后提交用户隐私协议审核…

MURF20100CTR-ASEMI快恢复对管封装、尺寸、参数

编辑&#xff1a;ll MURF20100CTR-ASEMI快恢复对管封装、尺寸、参数 型号&#xff1a;MURF20100CTR 品牌&#xff1a;ASEMI 芯片个数&#xff1a;2 芯片尺寸&#xff1a;102MIL*2 封装&#xff1a;TO-220F 恢复时间&#xff1a;50ns 工作温度&#xff1a;-50C~150C 浪…

k8s集群环境的搭建

1.环境规划 1.1 集群类型 Kubernetes集群大致分为两类&#xff1a;一主多从和多主多从。 一主多从&#xff1a;一个Master节点和多台Node节点&#xff0c;搭建简单&#xff0c;但是有单机故障风险&#xff0c;适合用于测试环境。 多主多从&#xff1a;多台Master和多台Node节点…

CMU 15-445 -- Two Phase Locking - 14

CMU 15-445 -- Two Phase Locking - 14 引言Lock TypesTwo-Phase LockingDeadlock Detection & PreventionDeadlock DetectionDeadlock PreventionHierarchical Lockingintention locks加锁协议 锁升级最佳实践显式加锁的相关SQL语句小结 引言 本系列为 CMU 15-445 Fall 2…

剑指offer(C++)-JZ15:二进制中1的个数(算法-位运算)

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 输入一个整数 n &#xff0c;输出该数32位二进制表示中1的个数。其中负数用补码表示。 数据范围&#xf…

【运维】DevOps全流程笔记(未完成)

运维笔记 DevOps基本流程Code阶段工具&#xff08;gitlab安装&#xff09;Build阶段工具&#xff08;Maven安装&#xff09;Integrate阶段工具JenkinsJenkins介绍Jenkins安装Jenkins入门配置 CI/CD操作集成Sonar Qube集成HarborJenkins流水线Kubernetes编排工具 DevOps全流程笔…

OJ练习第144题——将数组和减半的最少操作次数

将数组和减半的最少操作次数 力扣链接&#xff1a;2208. 将数组和减半的最少操作次数 题目描述 给你一个正整数数组 nums 。每一次操作中&#xff0c;你可以从 nums 中选择 任意 一个数并将它减小到 恰好 一半。&#xff08;注意&#xff0c;在后续操作中你可以对减半过的数…

基于YOLOv5的WiderFace人脸检测检测系统(PyTorch+Pyside6+YOLOv5模型)

摘要&#xff1a;基于YOLOv5的WiderFace人脸检测系统可用于日常生活中检测与定位人脸目标&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的人脸目标检测识别&#xff0c;另外支持结果可视化与图片或视频检测结果的导出。本系统采用YOLOv5目标检测模型训练数据集&…

ffplay播放器剖析(6)----音视频同步分析

文章目录 1. 音视频同步基础1.1 音视频同步策略1.2 音视频同步概念1.3 FFmpeg中的时间单位1.4 不同结构体的time_base/duration分析1.5 不同结构体的pts/dts分析1.6 ffplay中Frame结构体分析1.7 Vidoe Frame PTS获取及矫正1.8 Audio Frame PTS的获取 2.以音频为基准3.以视频为基…

了解Unity编辑器之组件篇Tilemap(五)

Tilemap&#xff1a;用于创建和编辑2D网格地图的工具。Tilemap的主要作用是简化2D游戏中地图的创建、编辑和渲染过程。以下是一些Tilemap的主要用途&#xff1a; 2D地图绘制&#xff1a;Tilemap提供了一个可视化的编辑器界面&#xff0c;可以快速绘制2D地图&#xff0c;例如迷…

jlink RTT调试 NRF52840

打开 J-Link RTT Viewer 搜索&#xff1a;**J-Link RTT Viewer ** 软件部分 代码部分 #include <stdbool.h> #include <stdint.h> #include "nrf_delay.h" #include "boards.h" //Log需要引用的头文件 #include "nrf_log.h"…

音频转换工具有很多,但是找到好用的还是得看这篇

在日常生活中&#xff0c;我们常常会遇到需要将音频文件转换成不同格式的情况。不过&#xff0c;有些音频转换软件可能需要安装繁琐的插件&#xff0c;这对于一些小伙伴来说可能不太方便。幸运的是&#xff0c;如今有许多免费的音频转换格式软件可供选择&#xff0c;让我们能够…

K3S 安装部署

一、方法1&#xff1a;利用官方源&#xff08;国外源&#xff09;直接一键安装 因 K3s 的核心组件镜像需从 gcr.io 拉取&#xff08;国内网络不通&#xff09;&#xff0c;所以需具备外网访问的环境&#xff0c;适用于服务器均在国外的环境选用&#xff0c;简单粗暴一键安装。…

mysql进阶1——proxysql中间件

文章目录 一、基本了解二、安装部署三、proxysql管理配置3.1 内置库3.1.1 main库表3.1.2 stats库表3.1.3 monitor库 3.2 常用管理变量3.2.1 添加管理用户3.2.2 添加普通用户3.2.3 修改监听套接字 四、多层配置系统4.1 系统结构4.2 修改变量加载配置4.3 启动加载流程 一、基本了…

聊一聊什么是JNDI数据源

大家好&#xff0c;我是G探险者。 我们平时开发项目&#xff0c;连接数据库那块&#xff0c;会采用连接池的方式连进行连接数据库&#xff0c;比如常见的durid,dbcp&#xff0c;c3p0等。那你有没有听过还有一个JNDI数据源呢&#xff0c;反正我以前是很少听说过。可能就是因为自…

梅尔频谱(Mel spectrum)简介及Python实现

梅尔频谱&#xff08;Mel spectrum&#xff09;简介及Python实现 1. 梅尔频谱&#xff08;Mel spectrum&#xff09;简介2. Python可视化测试3.频谱可视化3.1 Mel 频谱可视化3.2 STFT spectrum 参考文献资料 1. 梅尔频谱&#xff08;Mel spectrum&#xff09;简介 在信号处理上…

wordpress框架自定义添加page分页功能

先来看效果图&#xff1a; 一、在主题目录下的functions.php文件里&#xff0c;添加如下分页函数&#xff1a; /** * 数字分页函数 * 说明&#xff1a;因为wordpress默认仅仅提供简单分页&#xff0c;所以要实现数字分页&#xff0c;需要自定义函数 * Param bool $isHome 是…

工业静电监控系统的功能介绍

工业静电监控系统是一种用于监测和控制工业生产过程中静电现象的技术系统。静电是指由于物体间的电荷不平衡而产生的电场现象&#xff0c;它在工业生产中可能导致电击、火花、电磁干扰等质量问题。 工业静电监控系统主要通过使用静电传感器和控制设备来实现对静电场的监测和控…

Java反序列化(0):URLDNS的反序列化调试分析

URLDNS链子是Java反序列化分析的第0课&#xff0c;网上也有很多优质的分析文章。 笔者作为Java安全初学者&#xff0c;也从0到1调试了一遍&#xff0c;现在给出调试笔记。 一. Java反序列化前置知识 Java原生链序列化&#xff1a;利用Java.io.ObjectInputStream对象输出流的w…

中医药行业如何进行数字化转型?看天津同仁堂谈“有道有术有零代码”

张伯礼院士曾指出&#xff0c;中药制造的现代化水平&#xff0c;还停留在10%左右的阶段。中医药行业&#xff0c;老字号企业&#xff0c;该如何通过数字化焕发新活力&#xff1f; 天津同仁堂通过与伙伴云合作&#xff0c;零代码构建数字化系统&#xff0c;让技术与思维共同成长…