气抖冷~这破网

气抖冷

        当我们刷短视频刷的飞起的时候,突然加载不出来了,还可以骂运营商~当我们写一个网络应用,除了骂运营商,还能做什么?

进程/线程模型的选择

多进程模型

        一主多子进程模型,主进程负责socket的监听,子进程负责实际的业务处理。多进程模型可以利用多核处理器的优势,但进程创建和上下文切换的开销较大,因此不适合高并发场景。

        例如:同步阻塞多进程模型:服务端为每个新的客户端连接创建一个新的进程。每个进程独立处理一个客户端的请求,因此I/O操作是阻塞的,但不会影响到其他进程。由于每个进程独立处理一个客户端的请求,因此I/O操作是阻塞的,但不会影响其它进程。

多线程模型

        一主多子线程模型,主线程负责socket的监听,子线程负责实际的业务处理。多线程模型也可以利用多核处理器的优势,但在高并发场景下,线程数量过多可能导致资源竞争和调度开销增加。

        例如:同步阻塞多线程模型:服务器为每个新的客户端连接创建一个新的线程。与多进程模型类似,每个线程独立处理一个客户端的请求,但线程的创建和上下文切换开销小于进程。

对于多进程和多线程同步阻塞模型,它们一般能处理的规模取决于以下因素:

  • 系统资源限制:如操作系统对进程和线程数量的限制,以及系统内存和CPU资源。
  • 上下文切换开销:大量的进程或线程会导致频繁的上下文切换,影响性能。
  • 同步机制的开销:同步阻塞模型可能需要锁、信号量等同步机制,这些机制在高并发时可能成为瓶颈。
  • 应用程序的特性:不同的应用程序对资源的需求不同,例如CPU密集型、I/O密集型或内存密集型应用程序。

        在实际应用中,多进程和多线程同步阻塞模型通常适用于中等负载的场景,能够处理的客户端数量可能从几十到几千不等。

I/O模型的选择

        在Linux系统中,有几种常见的I/O模型,每种模型都有其特点和适用场景。

同步阻塞I/O

        在阻塞I/O模型中,应用程序执行一个系统调用,如read(),然后等待数据准备就绪并被复制到应用程序缓冲区。在此期间,应用程序被挂起(阻塞),直到I/O操作完成。适用于客户端数量较少且负载较轻的服务器应用程序。

同步非阻塞I/O

        在非阻塞I/O模型中,应用程序执行系统调用后,如果数据未准备就绪,调用会立即返回一个错误(通常是EWOULDBLOCK或EAGAIN)。应用程序可以继续执行其他任务或定期重试I/O操作。适用于需要同时处理多个I/O操作但不想使用多线程或多进程的情况。

I/O多路复用

        I/O复用模型使用select()、poll()或epoll()等系统调用,允许应用程序监视多个文件描述符,以确定哪个或哪些可以执行非阻塞I/O操作。应用程序在一个单独的线程或进程中阻塞等待这些系统调用之一。适用于需要处理大量并发连接的服务器,如Web服务器或数据库服务器。

信号驱动I/O
        信号驱动I/O模型允许应用程序为一个文件描述符安装一个信号处理函数,当数据准备就绪时,内核会发送一个信号给应用程序。应用程序不需要阻塞等待I/O操作,而是在收到信号后开始I/O操作。适用于需要快速响应I/O事件但不想在I/O操作上阻塞的应用程序。

异步I/O
        在异步I/O模型中,应用程序发起一个I/O操作后可以立即继续执行。当整个I/O操作完成时,应用程序会收到一个通知。与信号驱动I/O不同,异步I/O是在整个I/O操作完成后通知应用程序,而不仅仅是数据准备就绪。适用于需要最大化I/O并行性的高性能应用程序,如视频处理或科学计算。
        选择合适的I/O模型通常取决于应用程序的需求和预期的负载。例如,对于高并发服务器,I/O复用或异步I/O可能是更好的选择,因为它们可以更有效地管理大量的并发连接。对于简单的客户端应用程序或负载较轻的服务器,阻塞I/O可能就足够了。

网络协议的优化        

应用层协议优化

  • 长连接:增加连接的复用率,减少重复TCP三次握手与四次挥手、应用层握手的开销。在每秒请求次数比较多的时候,效果还是非常明显滴。例如HTTP1.1通过Connection: Keep-Alive维护长连接。
  • 缓存:使用内存等方式,来缓存不常变化的数据,降低网络 I/O 次数,加快应用程序的响应速度。例如DNS会在本机缓存已解析的域名,在缓存有效期间不必重新发起网络请求。
  • 压缩:使用protobuf等序列化的数据格式,压缩需要经过网络传输的数据量,提高程序的吞吐量。例如QQ NT就使用了protobuf作为通信协议。
  • 避免分片:动态探测mtu,避免数据包在网络传输中被二次分片。

传输层协议优化

  • 增大套接字缓冲区:读/写缓冲区满,就不能再接收/发送新的数据。通过setsockopt接口SO_RCVBUF、SO_SNDBUF选项来设置。
  • TCP Nagle算法:Nagle算法通过将多个小的消息组合成一个较大的消息来减少网络上的小分组数量。在一些对实时性要求比较高的场景可以考虑禁用它。通过setsockopt接口TCP_NODELAY选项设置。
  • TIME_WAIT优化:大量短时请求并发处理,容易看到大量处于TIME_WAIT状态的连接,会占用不少资源。
    • 减小 net.ipv4.tcp_fin_timeout 和 net.netfilter.nf_conntrack_tcp_timeout_time_wait ,使其资源尽快释放。
    • 增大处于 TIME_WAIT 状态的连接数量 net.ipv4.tcp_max_tw_buckets ,并增大连接跟踪表的大小 net.netfilter.nf_conntrack_max。
    • 开启端口复用:net.ipv4.tcp_tw_reuse,复用TIME_WAIT状态的端口。
    • 增大端口范围:net.ipv4.ip_local_port_range,支持更多连接。
  • 增大可打开的文件描述符个数:fs.nr_open(进程) 和 fs.file-max(系统),支持打开更多的scoket文件。
  • SYN Flood攻击缓解
    • 增大半连接的最大数量 net.ipv4.tcp_max_syn_backlog
    • 开启SYN Cookies:net.ipv4.tcp_syncookies,服务端不维护半连接。
    • 减少SYN_RECV状态重传SYN+ACK包的次数:net.ipv4.tcp_synack_retries
  • TCP keepalive:默认的keepalive重试次数及间隔时间太长,一般长达数小时
    • 缩短最后一次数据包到keepalive探测包的间隔时间:net.ipv4.tcp_keepalive_time
    • 缩短多个keepalive 探测包的间隔时间 net.ipv4.tcp_keepalive_intvl;
    • 减少 Keepalive 探测失败后,一直到通知应用程序前的重试次数 net.ipv4.tcp_keepalive_probes
  • 避免分片:避免发送TCP大包,某个分片丢失会导致整个TCP包重传;避免IP层分片,尽量在应用层传输数据的时候合理设置大小。

网络/链路层优化

  • 开启irqbalance:将(各种)硬件中断均匀地分配到多个CPU核心上,防止某个单一的CPU核心成为处理所有中断的瓶颈,从而提高系统的整体性能。
  • 开启 RPS、RFS:通过软件模拟的方式将软中断负载均衡到多个CPU上,将应用程序和软中断的处理,调度到相同 CPU 上,增加 CPU 缓存命中率。
  • 开启 RSS 多队列接收:它基于硬件的多个接收队列,将网络流量负载均衡到多个CPU上。
  • 使用DPDK/XDP技术,跳过内核协议栈,直接由用户态进程轮询处理网络请求。适合流量超级大的场景。
  • 关闭ICMP探测:禁止 ICMP 响应,即设置 net.ipv4.icmp_echo_ignore_all = 1

选哪个

        优化的方法千千万,适合自己的才是最好的

  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Fireplusplus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值