Unix Like, 网络

UDP SndbufErrors & ENOBUFS

最近一部分服务器上,遇到UDP发包速率太高会出现大量丢包的情况。这个丢包不是发生在中间网络设备上丢,也不在接收方上,而是发生在发送方kernel中。为什么会知道是在kernel丢的?因为用户空间程序的统计的发包量,跟内核统计的有很大差距,所以可以肯定用户空间把包交给内核后,内核并没有全发出去。 通过kernel的snmp,发现UDP的SndbufErrors计数器有很高的值:

这个计数器是在哪、什么情况下增长的?翻了一下kernel的源码,在net/ipv4/udp.c中找到两个,一个在udp_sendmsg()中: [cray […]

Read more
网络

KCP-GO的重传机制以及带宽利用率的提升

1. KCP 按KCP的README,这协议并不是设计来跑大流量的: TCP是为流量设计的(每秒内可以传输多少KB的数据),讲究的是充分利用带宽。而 KCP是为流速设计的(单个数据包从一端发送到一端需要多少时间),以10%-20%带宽浪费的代价换取了比 TCP快30%-40%的传输速度。 从它的技术特性,你也可以得知这协议相对TCP的重点改进是在重传上,而不是拥塞控制。那它为什么快(某些情况下)呢?一方面,它重传机制的改进,丢包后可以更早重传,对方更早收到补发的包,更早能把数据递交给应用层,缓冲区的释放更快,发送方也能更早继续发送后续的数据;另一方面,它技术特性里面有个“非退让流控”,名字听起 […]

Read more
操作系统, 服务器, 网络

PowerDNS Recursor设定默认EDNS Client Subnet值

授权DNS服务器可以根据递归DNS服务器发送的EDNS Client Subnet(ECS)中的值,返回不同的结果。如果客户端是通过内网IP向递归DNS服务器发起查询的,而且递归DNS服务器发出的递归查询使用的公网IP跟客户端使用的公网IP不是一个地区时,就无法给客户端提供一个最优的解析结果了。 PowerDNS Recurse 4.2增加了一个设置“ecs-add-for”,可以指定哪些subnet允许作为ECS的值,对于不允许作为ECS值的subnet,将会取ecs-scope-zero-address的值作为ECS的值。所以通过这两个设置可以为内网客户端设定一个默认的ECS值。 配置文件 […]

Read more
Unix Like, 操作系统, 服务器, 网络, 运营维护

Nginx ssl_preread传递客户端IP

ssl_preread是基于L4的反代方案,TLS SNI握手时客户端会提供域名,所以可以让Nginx在无需完成TLS握手的情况下,就根据域名进行后端服务器的选择。简单来讲,你只需要给后端服务器配置一个SSL证书,而提供反代功能的Nginx则无需配置。文档见此:http://nginx.org/en/docs/stream/ngx_stream_ssl_preread_module.html 因为这是L4反代,所以通过“proxy_set_header”传递客户端IP的方法是行不通的。其实传递客户端IP的解决办法跟上一篇文章类似:L4(传输层)IP透明反向代理的实现(传递客户端真实IP),ng […]

Read more
Unix Like, 服务器, 网络

L4(传输层)IP透明反向代理的实现(传递客户端真实IP)

这种需求,一般来说,会在应用层加个标记标明客户端的IP,例如说HTTP,就是添加个请求头的事情。但并不是所有服务器程序、协议你都能这样下手。所以能不能在不对协议和服务器程序本身做任何改动的情况下,传递客户端的IP呢? 最直接的方法应该就是,把L3的源IP改掉,没对协议进行任何改动,对上层完全透明。先来看看改了L3的source IP会出现什么问题: 上图中的A是个L4负载均衡,Router会把来自Internet的客户端请求转发给A,A再根据策略转发到B、C或D。 假设这时A选择了B,A把请求转发给B时,把L3的源IP改成了客户端的IP,那B收到数据包后,根据B系统上的路由表,回复的包会直接经 […]

Read more
Unix Like

CLion调试Linux Kernel

1. 编译Kernel 先按照https://www.kernel.org/doc/html/latest/dev-tools/gdb-kernel-debugging.html说明的config设定编译内核并且安装到guest上。 menuconfig中按“/”是可以搜索的,例如要找“CONFIG_GDB_SCRIPTS”,按“/”输入“GDB_SCRIPTS”。 qemu启用了virtio的话,记得选上VIRTIO_BLK和VIRTIO_NET。 2. QEMU 2.1 关闭KVM 关闭KVM,关闭KVM,关闭KVM,重要的事情说三次!不然step by step的时候,会无限跳到arch […]

Read more
Unix Like, 操作系统

千兆公网带宽的TCP sendbuffer与receivebuffer调整

不知道有多少人留意过,使用千兆公网带宽传输数据时,只要距离稍微远点,就无法跑满千兆。对于这种情况,可能第一反应是“线路繁忙,公网带宽不足,跑不满很正常”。不过如果你有在不同地区的多台千兆设备间传数据的经历的话,你大概会发现,最大传输速度跟延迟成负相关。 首先丢出个公式:

TCP有ARQ机制,已发出的数据要收到ACK后才能丢弃。因为至少要等一个RTT才能收到ACK,所以sendbuffer要至少能存放一个RTT内能发出的数据量。另外,TCP的拥塞控制也会根据接收方的receivebuffer大小限制数据的发出速率。因此,如果想达到 […]

Read more
Unix Like, 操作系统, 网络

Linux IPv4 forward自动丢弃源IP为系统已绑定的IP的问题

A是路由,其上做了策略,一部分符合特定条件的流量,是要转发到B进行封装处理,A和B之间做了数个VLAN,B根据VLAN应用不同的策略。 不过这里的问题是,B的默认网关也是A(环路问题是不存在的,已经有对应规则处理),所以B自身发出的流量也会由A应用策略,转发回给B自己。而B收到src IP是local IP(系统已绑定的IP)的包时,kernel会直接丢弃数据包,所以除了B自己的数据包,B都能正常封装。 解决这个问题的一个方法,是让A在把数据包转发给B前,做一次SNAT,这样B收到的数据包,src IP就是A的IP了。其实SNAT并没有什么影响,A对NAT也有hardware offload, […]

Read more
Unix Like, VPN, 网络

TCP Sendbuffer Size与RTT的问题

最近从A服务器下载数据时,发现如果走B服务器的VPN下载,速率只能跑到300KB左右,但是B从A直接下载却能跑到1MB+/s,B到本地的速度也远超过A到B的速度,其实一开始我以为是VPN实现的问题,有段时间在思考如何优化VPN,但是尝试了其它VPN实现,问题并没有解决。后来发现,走B的代理而不是VPN,速度正常。 本地到B的RTT大约160ms,B到A大约50ms。 Wireshark抓包,对tcp sequence number统计了下: 放大点看: 大概每传输60KB,就要等大约200ms才能继续。200ms刚好差不多等于本地走VPN到A的RTT。传这60KB,只花了大概10ms,忽略这1 […]

Read more
Unix Like, 服务器

双路超线程物理服务器的QEMU CPU affinity调整

首先运行 virsh capabilities 查看物理机物理核心及其线程与逻辑处理器(线程)的关系:

其中的socket_id代表CPU的槽位,core_id代表CPU物理核心,siblings表示哪些逻辑处理器(线程)是属于同一个物理核心的。 例如id为0以及8的逻辑处理器,都属于同一个CPU槽位且属于同一个物理核心。 在这台物理机上建立的虚拟机,想得到最佳的性能,首先不要跨CPU插槽,其次,不要让多个虚拟机CPU共享同一个物理核心。 根据上面的信息,4核心8线程的虚拟机CPU亲和度配置如下: [crayon-616d268 […]

Read more