HTTP2 URL请求过长访问失败的问题

使用过长的url通过H2访问的时候, 容易出现请求被reset掉, 但是HTTP/1.1请求没事

  • TLSv1.2 (IN), TLS alert, close notify (256):
  • Empty reply from server
  • Connection #0 to host api.k.sohu.com left intact
    curl: (52) Empty reply from server
  • Closing connection 0

打开nginx debug 日志可以看到

client sent too large header field while processing HTTP/2 connection

这是因为HTTP2有一套自己的优化参数, 主要跟两个参数有关:

http2_max_header_sizehttp2_max_field_size

http2_max_field_size 是HPACK压缩的header大小(H2的特性, 头部压缩), 默认值4k

http2_max_header_size HPACK解压后的header大小,默认16k

需要特别留意的是, 1.19.7版本以后统一使用large_client_header_buffers 来控制

这几个参数都可以根据单独server 来使用的

http://nginx.org/en/docs/http/ngx_http_v2_module.html#http2_max_field_size

参考文档:

https://phabricator.wikimedia.org/T209590

亚马逊lightsail免费期的收费项目

亚马逊的lightsail提供了3个月的免费试用, 有$3.5 $5 $10的主机选择

对于刚搬迁过来的用户可能会对一些收费不了解, 这里就我踩过的坑介绍下

来看看一份账单

这里有两个收费项目:

  1. snapshot的存储是收费的, 按照容量和保存时间收费
  2. 静态IP如果没有绑定到实例, 也是需要收取闲置费用的

当然, 使用container, database, 额外的存储/IP/镜像等, 也是收费项目

个人认为静态IP在实例被释放后没有绑定到新实例, 会是新手很容易忽略的收费陷阱

从linode迁移到亚马逊lightsail

我是linode 10多年的老用户了, 从2010年就在上边安家, 期间从fremont搬迁到东京, 又搬回来,来回折腾过几次

一开始是大熊推荐的, linode的确是海外云主机最好的选择: 因为稳定.

到了最近几年, linode变成了”稳定”的慢和移动访问”稳定”的丢包, 一言难尽

今年年初刚好发现亚马逊推出了lightsail的服务, 配置类似于EC2的t2, 可定制化更少, 但是流量包更大

对比下linode 和 lightsail的方案, 可以看到lightsail的磁盘大一些, 流量包也大一些(其实差不多, 因为aws是进出双向计算, 只有超出限额才改成output流量计费)

相比硬件配置, 网络才是让我下决心搬迁的主要原因, 我lightsail节点是新加坡的, 广州电信访问大概是46ms, 广州移动访问是45ms, 广州联通访问是88ms, 都不丢包, 划重点: 不丢包!

联通线路
电信线路
移动线路

而linode的fremont 大概是160-180ms, 间歇性丢包, 尤其是晚上移动线路, 东京机房也差不多

电信线路
移动线路

这是因为亚马逊实现了跟三大运营商的直连, 而linode 没有, 这对于服务国内用户来说是一锤定音的因素, 更何况还有3个月的免费试用期

相信看到这里, 苦于linode网络的, 都已经忍不住去注册了, 这里放一下连接

https://aws.amazon.com/ 选择lightsail服务

nginx upstream check module TCP check检测漏洞

upstream test_check_bin {
server 10.19.127.22:8080;
server 10.19.127.57:8080;
server 10.19.126.6:8080;

keepalive 32;
check interval=10000 rise=2 fall=3 timeout=3000 default_down=false;

}

我们使用的是一个臭名昭著的模块 , 这个模块的作者去了淘宝后便只有tengine里边的模块得到更新了

https://github.com/yaoweibin/nginx_upstream_check_module

目前发现了在当前代码存在两个问题:

  1. TCP检查在几种情况下会失效, 比如交换机挂掉, upstream机器网线被拔了, upstream机器crash了
  2. TCP检查的rise count 存在不增加的情况, 主要是裸JAVA和JAVA容器(java -Dspring.profiles.active=local -jar httpbin-gateway-test.jar),裸python -m SimpleHTTPServer 80之类

第一个问题是因为这个版本的upstream check TCP代码使用的keepalive模式, 根据这个文章的解释TCP Keepalive的心跳包是7200s,两个小时,一旦建立,没有收到主动关闭请求的话在探测端会一直保留establish的状态

https://m.haicoder.net/note/tcpip-interview/tcpip-interview-tcp-keepalive.html

当upstream端突然硬件故障/交换机挂掉/网卡被拔之类的极端情况出现的 时候, nginx 基于keepalivedTCP检测是没办法捕获到这个情况的(检测模块没收到RST/或者dst unr包)

在正常情况下, 比如upstream 端web服务器 STOP了, web服务器oom被系统kill了, docker 实例被stop/kill了, 都会触发关闭连接的请求包 给到nginx 端, 能识别到服务down了

这个是upstream端被kill了
docker kill/stop 都会发包告知nginx TCP监测端

从tengine这个模块的最新代码看, 作者也意识到了这个问题, TCP检测把need_keepalive参数从1改成了0

这个1表示need_keepalive, tengine修改为0了
ngx_check_conf_t 模块这个结构体的定义

这个参数变成0之后会影响clean_event的操作, 每次检测完毕后会close掉连接,每个检测周期都会重新发起TCP连接

need_keepalive参数控制了连接是否销毁的行为

第二个问题: rise counts 不增加, 这个通常都是upstream 端listen 模式有问题导致, 它并没有正确的定期回包, 通常情况下, nginx, apache都能正常的主动回包让rise counts增加

大多数upstream端主动发送包(确认是否存活), 否则很快就会close

python java这些裸起的一些简单服务就没有定期主动回包, 而在这个版本的代码中, 会判断这个connection是否存在, 如果存在则return了导致计数器不会增加

tengine的新代码是去掉了connection != NULL的判断条件

不过, 划重点: 无论是否回包, rise counts 是否增加,并不影响TCP监测的存活性, TCP监测keepalive模式仅仅以能否建立连接(刚启动时)/是否收到upstream的异常包为判断依据

总结: 为了避免过于复杂的处理逻辑, tengine去掉了keepalive的TCP探测,每次请求完都销毁连接,下次探测再重新协商请求

这里给下针对这个问题的patch:

https://www.4os.org/patch/nginx_upstream_check_tcp.patch

使用利民散热硅胶垫 改造 macbook air 2020 散热

macbook air 2020款intel 处理器开始 CPU就没有风扇直连了

日常使用问题倒是不太大, 但是开视频会议的时候特别容易撞温度墙降频, 机器卡顿

发现有一款神器, 叫散热硅胶垫, 可以用于改造macbook air 散热, 有莱尔德/利民等不同品牌不同型号

Laird Tflex HD90000 Series Thermal Pad For M2 RTX 3000 3080 3090 Card Video  Memory,7.5W/mK,80x40MM,1.0,1.5,2.0,2.5mm Thick,Soft| | - AliExpress
莱尔德HD90000, 许多显卡的散热标配, 但是容易出油
利民 12.8W 之前的散热神器, 虚标

利民15w
一般大家其实都是用来显卡上的

莱尔德散热效能没得说, 缺点是容易出油并且会析出银粉不好清理, 于是我选用了利民, 有12.8W和 15W两种规格, 来都来了, 自然是选15W这款

打开机器后盖, 裁剪尺寸, 贴在散热器后边即可

从geekbench的数据看, 性能提升挺明显的

从cinebench测试看, 多核性能提升了20%, 单核性能由于没有撞温度墙所以不明显

待机温度也很友好了, 45°左右

散热垫评测:

https://www.bilibili.com/video/BV1d44y1q7vf?spm_id_from=333.999.0.0

小米路由R1D ipv6设置

分为普通模式和中继模式, 略有不同

  • 中继模式需要配置

/etc/config/ipv6
config ipv6 settings
list if_on "lan"
option enabled "1"
list if_on "ipv6"
option enabled "1

/etc/config/network

config interface 'lan6'
option ifname '@lan'
option proto 'dhcpv6'

可以适当配置ipv6的DNS, 非必须

  • 普通模式需要配置

/etc/config/ipv6
config ipv6 settings
list if_on "wan"
option enabled "1"
list if_on "ipv6"
option enabled "1

/etc/config/network

config interface 'wan6'
option ifname '@wan'
option proto 'dhcpv6'
list dns '240c::6666'
list dns '240c::6644'

然后重启或者/etc/init.d/network restart即可

rp_filter和fwmark base 策略路由

  • 前提:

先说下网络环境, 这边架了个tunnel, 之前无论是全部走tunnel 还是部分目标IP走tunnel都没有问题, 实现如下

ip rule add from 10.4.224.100 table routeTableName

ip route add $line via 172.16.172.1 dev tunnel (table routeTableName)

  • 新的需求: 根据部分协议,比如TCP来走这个路由, 实现办法是

iptables -t mangle -A PREROUTING -s 10.4.224.100/32 -d 10.0.0.0/8 -p tcp -m tcp -j MARK --set-xmark 3

ip rule add from 10.4.224.100 fwmark 3 table tun

在这个路由表使用的策略路由则不生效了, 相同的语句导致无法访问网络了

ip route add $line dev tunnel table tun

  • 听包看看:

在tunnel的对端服务器能看到对端回包后后续传输失败了

在本地linux 网关的tunnel听包可以看到回包也过来了

在本地linux 网关的内网听包能看到只有客户端的发包没有收到回包

那么问题就发生在tunnel 到 内网网卡这一段, 包要么是路由不对,要么是被drop了, 由于之前是可以直接访问的, 那么路由的可能性很小

  • 问题定位检测:

使用如下方式确认回包是否被drop了,配置:

sysctl -w net.ipv4.conf.default.log_martians=1
sysctl -w net.ipv4.conf.all.log_martians=1

发现有如下的检测日志:

IPv4: martian source 10.4.224.100 from 122.13.86.120, on dev tunnelX
IPv4: martian source 10.4.224.100 from 122.13.86.120, on dev tunnelX

这里由于是reverse path filter, 原理是把源和目标调换确认该设备接口是否是最佳接口, 显然回包被认为是不合适的包, 被过滤掉了

  • 问题解决:

问题就简单了, 设置rp_filter即可

sysctl -w net.ipv4.conf.default.rp_filter=2

sysctl -w net.ipv4.conf.all.rp_filter=2

  • 问题解析:

那么问题来了, 为什么原来的简单策略路由就可以, 加了–set-mark 3后, 基于fwmark的就不行呢?

从听包可以看到原有的策略路由是可以正常返回的, 包括tunnel和内网网卡

推测很大可能是因为我们使用了 ip rule add from 10.4.224.100/32 table routeTableName的方式能让rp_filter检测到回程数据包的reverse path是合理的

而rp_filter大概率是无法识别到fmwark的策略路由的, 检测的时候发现回包数据不合理被drop了

如何确认以上这番推测是否合理呢? 这里做了个测试, 从tunnel对端的机器使用tunnel接口ping 10.4.224.100

ping 10.4.224.100 -I tunnelX
PING 10.4.224.100 (10.4.224.100) from 172.16.172.1 tunnelX: 56(84) bytes of data.
^C
--- 10.4.224.100 ping statistics ---
77 packets transmitted, 0 received, 100% packet loss, time 77858ms

查看本地linux的日志可以看到数据包被drop了

Mar 18 09:37:25 gw kernel: IPv4: martian source 10.4.224.100 from 172.16.172.1, on dev tunnelX
Mar 18 09:37:25 gw kernel: IPv4: martian source 10.4.224.100 from 172.16.172.1, on dev tunnelX

由于是reverse path 校验嘛, 给它加个路由

ip route add 172.16.0.0/16 dev tunnelX table myRouteTable

于是, 通了

ping 10.4.224.100 -I tunnelX
PING 10.4.224.100 (10.4.224.100) from 172.16.172.1 tunnelX: 56(84) bytes of data.
64 bytes from 10.4.224.100: icmp_seq=1 ttl=62 time=2.22 ms
64 bytes from 10.4.224.100: icmp_seq=2 ttl=62 time=37.9 ms

至于为什么ping值这么飘忽…因为这个是wifi的IP啊, 我去毒打wifi管理员了



  • 背景资料:

关于rp_filter的问题可以参考本站这个链接:

/usr/share/doc/kernel-doc-2.6.32/Documentation/networking/ip-sysctl.txt rp_filter -

INTEGER 0 - No source validation. 不检测源

1 - Strict mode as defined in RFC3704 Strict Reverse Path Each incoming packet is tested against the FIB and if the interface is not the best reverse path the packet check will fail. By default failed packets are discarded.

严格检测模式

2 - Loose mode as defined in RFC3704 Loose Reverse Path Each incoming packet's source address is also tested against the FIB and if the source address is not reachable via any interface the packet check will fail.

松散检测模式, 只要有一个设备接口有这个地址就可以

Current recommended practice in RFC3704 is to enable strict mode to prevent IP spoofing from DDos attacks. If using asymmetric routing or other complicated routing, then loose mode is recommended. The max value from conf/{all,interface}/rp_filter is used when doing source validation on the {interface}. Default value is 0. Note that some distributions enable it in startup scripts.

  • 参考资料:

https://blog.csdn.net/dog250/article/details/7947705

aws lightsail ssh 挂掉如何登录

在尝试调整sshd端口的时候不小心把ssh弄挂了, 由于vps里边也是有防火墙的,外边进不去,控制台也进不去,因为amazon的lightsail 实际上并没有console控制台, 它的控制台也是通过ssh登录的

这个时候需要如下步骤来拯救机器和数据

1.    打开 Amazon Lightsail 控制台

2.    创建实例的手动快照

3.    在 Snapshots (快照)选项卡上的 Manual snapshots (手动快照)项下,选择新快照旁边的三个点。

4.    选择 Create new instance (创建新实例)。

5.    选择与上一个实例相同的可用区域。

6.    选择 Add launch script (添加启动脚本),然后添加以下脚本

sudo sed -i 's/Port /#Port /g' /etc/ssh/sshd_config
sudo systemctl restart sshd.service
sudo systemctl stop firewalld.service
sudo systemctl disable firewalld.service
sudo systemctl enable sshd
sudo systemctl restart sshd
sudo systemctl enable sshd.service
sudo systemctl restart sshd.service

7.    选择新的实例计划,或使用与之前的实例相同的计划。

8.    输入实例的名称,然后选择 Create instance (创建实例)。

新实例开始运行后,等待 10 到 15 分钟,然后尝试使用基于浏览器的 SSH 控制台连接到该实例。

注意:如果以前的实例具有静态 IP 地址,则可以在新实例上使用它。分离静态 IP 地址,然后从 Networking (联网)选项卡将其附加到新实例。有关更多信息,请参阅 Amazon Lightsail 中的静态 IP 地址

如果以上问题仍不能修复, 则需要尝试为机器配置会话管理器, 这个就比较复杂了,仅供参考

https://lightsail.aws.amazon.com/ls/docs/en_us/articles/understanding-static-ip-addresses-in-amazon-lightsail

SSH 服务已关闭

如果 SSH 服务未在实例上运行或未处于活动状态,则 SSH 连接将失败,并且您会收到 UPSREAM_NOT_FUND [519] 错误消息。要解决此问题,请为您的 Lightsail 实例配置 AWS Systems Manager 会话管理器服务。配置会话管理器后,在没有 SSH 服务的情况下访问实例,然后修复 SSH 问题。

SSH 问题的基本故障排除步骤包括:

  • 请查看 /var/log/auth.log 或 /var/log/secure 文件中的 SSH 身份验证日志以识别错误,具体取决于操作系统的版本。
  • 测试 SSH 配置文件语法,然后更正所有错误。
sudo sshd -t
sudo systemctl restart sshd

参考文档: https://aws.amazon.com/cn/premiumsupport/knowledge-center/lightsail-resolve-ssh-console-errors/

APNIC 区域不准确的情况

bilibili.com广州电信区域发现无法访问, 这边上网是根据APNIC的CN列表来的

结果发现8.134.32.222 这段的IP无法访问, 从搜狗查看是阿里云广东的节点,跟APNIC的数据集有冲突,APNIC显示是新加坡

于是用CNNIC校验了下,发现了矛盾的地方,CNNIC显示是CN Aliyun,但是mnt-by数据是SG新加坡, 不知道是不是跟新加坡买了这一段IP

ffmpeg av1编码

AV1编码由来

Apple、亚马逊、思科、 Google、英特尔、 微软、Mozilla 以及 Netflix 等厂商又共同组建了 Alliance for Open Media(开放媒体联盟)并在 2018 年推出了对抗 H.265 的新视频编码 AV1(AOMedia Video 1)

AV1编码优缺点

1.     优点

可以在同等质量下, 相对于H265/VP9  节省 30%+的码率, 相当于H264节省50%+的码率

libaom-av1 can save about 30% bitrate compared to VP9 and H.265 / HEVC, and about 50% over H.264, while retaining the same visual quality.

H264: 112m     H265: 55M     av1:  32M

2.     缺点

解码/编码非常耗费CPU, 目前未见到有编码级别的硬件加速

1)     解码, 从youtube的介绍看AV1 需要一台功能强大的计算机, 暗示了CPU耗费巨大, 测试了macOS和win10, 都能正常播放, 但是耗费的CPU比VP9多20~50%

从文档看, 解码级别的硬件加速已经有了, 包括intel 12代cpu和 nvidia的CUDA都可以

2)     编码: 目前没看到有硬件加速方式, 评价最好的为svt-av1编码

a)    Libaom-av1

             默认av1编码 参数  速率 基本处于不可用状态, 只有0.00x 倍, 需要通过调整-cpu-used参数和使用2pass 方式实现性能码率的均衡, 不过也挺慢的

可以看到在cpuused 5 附近, 码率和质量达到了比较好的平衡

ffmpeg -y -i Black.Widow.mp4 -ss 00:39:06 -to 00:42:00 -c:v libaom-av1 -strict -2 -b:v 3000K -maxrate 6000K -cpu-used 8 -pass 1 -f matroska NUL & d:/ffmpeg/bin/ffmpeg -i Black.Widow.mp4 -ss 00:39:06 -to 00:42:00 -c:v libaom-av1 -strict -2 -b:v 1500K -maxrate 3000K -cpu-used 5 -pass 2 black.libaom-av1.sample.2pass.mkv

b)    Svt-av1 : intel 和 Netflix的方案

libsvtav1 is the Intel x86-64 codec for AV1. Compile with --enable-libsvtav1. See ​FFmpeg doc and ​upstream doc.

The range of options are similar to that of libaom (aomenc). It is supposed to be faster than libaom while having comparable quality.

40 核 Intel(R) Xeon(R) CPU Silver4210 @2.2G , windows server 2019 平台, 默认参数下可以实现2X 的编码, 代价是质量稍微有点模糊

ffmpeg -y -i Black.Widow.mp4 -ss 00:39:06 -to 00:42:00 -c:v libsvtav1 -preset 4

c)     Rav1e

Rav1e claims to be the fastest software AV1 encoder, but that really depends on the setting.  速度不行, 目前看暂不可用

d)    爱奇艺自研方案

为了进一步提高编码效率,爱奇艺基于AV1标准独立自主研发出QAV1编码器,极大缓解了AV1计算复杂度高、编码时间长的问题,进而加速AV1应用效率。测试显示,与目前最流行的编码器X265相比,QAV1编码器可以节省40%以上码率,进而可以减小将近一半的带宽;在同等的压缩率下,QAV1编码器比由Netflix与英特尔联合推出的开源编码器SVT-AV1快5倍左右。借助QAV1编码器,AV1视频播放会更加流畅,同时帮助用户节省大量流量。

e)    商业化方案 微帧科技

参考文档

https://trac.ffmpeg.org/wiki/Encode/AV1

https://sspai.com/post/59174

https://gitlab.com/AOMediaCodec/SVT-AV1

https://www.streamingmedia.com/Articles/Editorial/Featured-Articles/AV1-Has-Arrived-Comparing-Codecs-from-AOMedia-Visionular-and-Intel-Netflix-142941.aspx?utm_source=related_articles&utm_medium=gutenberg&utm_campaign=editors_selection