nginx range回源 和 range slice回源

range request in nginx reverse proxy

nginx proxy_cache 模式下是否支持range, 取决于源站是否返回了: Accept-Range Header 

在源站没有明确支持range的请求下, 即便nginx cache 了整个文件, 也不会响应任何range 请求, 会返回整个文件

这个行为方式可以通过 修改proxy_force_range on;来修改

Syntax:proxy_force_ranges on | off;
Default:proxy_force_ranges off;
Context:httpserverlocation

This directive appeared in version 1.7.7.

Enables byte-range support for both cached and uncached responses from the proxied server regardless of the “Accept-Ranges” field in these responses.

nginx 有个特殊的模块叫做http_slice_module, 可以支持分片回源

比如如下配置, 会以1M为文件块跟源站回源, 并存成多份1M分割的cache

slice              1m;

    proxy_cache_key    $host$uri$slice_range;

    proxy_set_header   Range $slice_range;

    proxy_http_version 1.1;

    proxy_cache_valid 200  206 300m;

从测试看, 即便开启了proxy_force_range on和slice range 回源, 在源站没有明确返回Accept-Range的情况下, nginx 依然不会使用slice range回源, 保持了良好的适配性

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_force_ranges

https://forum.nginx.org/read.php?2,281946,281946#msg-281946

proxy_pass 建议写法

            location /v {
                proxy_pass https://gs.x.sohu.com;
            }
看个简单的例子, 一般为了方便我们会直接把域名写在proxy_pass的后边, 这会导致当这个域名无法解析的时候,比如机房下线了,比如第三方回源的域名被摘掉了, 导致nginx restart失败
建议的写法是:
                location /v {
                     set $new_host "gs.x.sohu.com";
                     proxy_pass https://$new_host;
                }
两者的不同之处在于: 
1. proxy_pass直接跟域名的话, 会且只会在nginx 服务起来的时候解析一次, 失败则起不来
2. proxy_pass跟一个域名变量的话, 是调用resolver的, 跟随resolver的配置, 包括有效时间等, 有请求的时候才解析, 失败了也不影响全局服务

Meanings of fields in /proc/net/dev?

seq_printf(seq, "%6s:%8lu %7lu %4lu %4lu %4lu %5lu %10lu %9lu "
       "%8lu %7lu %4lu %4lu %4lu %5lu %7lu %10lu\n",
       dev->name,
       stats->rx_bytes,
       stats->rx_packets,
       stats->rx_errors,
       stats->rx_dropped + stats->rx_missed_errors,
       stats->rx_fifo_errors,
       stats->rx_length_errors + stats->rx_over_errors +
        stats->rx_crc_errors + stats->rx_frame_errors,
       stats->rx_compressed,
       stats->multicast,
       stats->tx_bytes,
       stats->tx_packets,
       stats->tx_errors,
       stats->tx_dropped,
       stats->tx_fifo_errors,
       stats->collisions,
       stats->tx_carrier_errors + stats->tx_aborted_errors +
        stats->tx_window_errors + stats->tx_heartbeat_errors,
       stats->tx_compressed);

ffmpeg剪辑视频

标准例子:

ffmpeg -i input.mp4 -ss 01:19:27 -to 02:18:51 -c copy output.mp4

这里-ss 表示开始时间, -to 表示结束时间

从开始位置截取多少时长的内容:

ffmpeg -i input.mp4 -ss 00:01:10 -t 00:01:05 -c copy output.mp4

这里引用了-t : duration 参数, 控制了截取视频的时长

那么, 以上做法有什么缺点么?

有的, 一个是慢, 一直在seeking 那个时间的样子, 另一个是画面容易在开始时候黑屏

优化方式:

ffmpeg -ss 01:19:27 -i input.mp4 -to 02:18:51 -c copy output.mp4

这里的技巧是把-ss提前了, 相当于让ffmpeg索引到关键帧, 缺点是会重置时间, 所以这里的-to 参数就相当于-t duration了

参考文档:

https://www.arj.no/2018/05/18/trimvideo/

openssl 探测证书过期时间

true | openssl s_client -connect IP:443 -servername hostname 2>&1 | openssl x509 -noout -text -certopt no_header,no_signame,no_pubkey,no_sigdump,no_aux

这边一直都是用这个来探测证书的健康的, 在内网的使用还可以, 在公网探测中就很容易出现僵死的情况

后来在sererfault.com查到可以用timeout + 命令来解决

https://serverfault.com/questions/361464/is-it-possible-to-set-a-timeout-on-openssls-s-client-command

测试时发现”timeout 5 true | openssl …” 的管道会失败, 在公网的探测就傻兮兮的只能用了

timeout 5 openssl s_client -connect IP:443 -servername hostname 2>&1 | openssl x509 -noout -text -certopt no_header,no_signame,no_pubkey,no_sigdump,no_aux

缺点是每条指令都要等5秒, 当然, 结合多进程问题也不是太大…

直到今天, 才发现自己摆了个乌龙, 可以使用timeout 5 bash -c “true | openssl s_client… “, true可以处理实时正常结果, timeout可以处理异常结果

timeout 5 bash -c "true | openssl s_client -connect IP:443 -servername hostname 2>&1 | openssl x509 -noout -text -certopt no_header,no_signame,no_pubkey,no_sigdump,no_aux "

aws lightsail ipv6 路由问题

OS 为: amazon linux 2, 当开启ipv6.forwarding的时候, 发现路由就不通了

sysctl -w net.ipv6.conf.all.forwarding=1

#ping6 www.qq.co

connect: Network is unreachable

netstat -nr6 也能看到没有default route, 此时ipv6地址也无法被外部访问

如果关闭ipv6 forwarding, 那么就有默认路由, 也能ping通外部和被访问

::/0 fe80::7c:6bff:feef:ca54 UGDAe 1024 2 9 eth0

能看到路由有一个很特别的标志UGDAe, UpGatewayDynamicAllonlinkExpires

E(e): It maps to RTF_EXPIRES. It means the route has a non-infinite lifetime. In this case, the kernel probably learned the route dynamically from a RA (Router Advertisement).

这个路由其实是动态广播的, 那么这个现象就跟一个参数有关了

net.ipv6.conf.interface.accept_ra

Accept Router Advertisements; autoconfigure using them.

It also determines whether or not to transmit Router Solicitations. If and only if the functional setting is to accept Router Advertisements, Router Solicitations will be transmitted.

Possible values are: 0 Do not accept Router Advertisements. 1 Accept Router Advertisements if forwarding is disabled. 2 Overrule forwarding behaviour. Accept Router Advertisements even if forwarding is enabled.

Functional default: enabled if local forwarding is disabled. disabled if local forwarding is enabled.

Nb: per interface setting (where “interface” is the name of your network interface); “all” is a special interface: changes the settings for all interfaces

默认系统这个参数是1, 当开启forwarding的时候, 不接受路由广播, 所以这个场合, 应该修改为2, Accept Router Advertisements even if forwarding is enabled.

sysctl -w net.ipv6.conf.all.forwarding=1
sysctl -w net.ipv6.conf.eth0.accept_ra=2

备注:

 UP U
 GATEWAY G
 REJECT !
 HOST H
 REINSTATE R
 DYNAMIC D
 MODIFIED M
 DEFAULT d
 ALLONLINK a
 ADDRCONF c
 NONEXTHOP o
 EXPIRES e
 CACHE c
 FLOW f
 POLICY p
 LOCAL l
 MTU u
 WINDOW w
 IRTT i
 NOTCACHED n

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在实例被释放后没有绑定到新实例, 会是新手很容易忽略的收费陷阱