分类 OS 下的文章

本文采用知识共享 署名-相同方式共享 4.0 国际 许可协议进行许可。
访问 https://creativecommons.org/licenses/by-sa/4.0/ 查看该许可协议。

Nginx 是一个 HTTP Server,类似的项目有 Apache、Httpd、IIS 等

1) Nginx VS Apache

  • Nginx
    • 轻量
    • 并发高:异步非阻塞,Apache 是阻塞的,默认只能同时处理 256 个请求(256 进程)
    • 高度模块化:模块编写成本低
  • Apache
    • URI Rewrite 出色
    • 模块历年沉淀,泛而全
    • 稳定、Bug 少

2) Configuration https://github.com/WarsFeng/Nginx_Configuration

基于阿里翻译的文档整理:https://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_core_module.html

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

# user nginx; # 进程运行用户
user nginx nginx; # 进程运行用户和用户组
worker_processes auto; # 进程数 auto/x 建议 CPU 线程数 + 1
worker_rlimit_nofile 65535; # 单进程最多打开的文件描述符数,由于请求分配不会均匀,建议直接设成与 ulimit -n 一致
#error_log /var/log/nginx/error.log; # 全局错误日志
error_log /var/log/nginx/error.log info; # 全局错误日志 日志类型[ debug | info | notice | warn | error | crit ]
pid /run/nginx.pid; # 进程文件

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf; # 导入其他位置配置文件

events {
    # 参考事件模型, 各类型 OS 支持的模型不同, Linux 推荐 epoll
    # [ kqueue | rtsig | epoll | /dev/poll | select | poll ]
    use epoll; 
    # 单进程最大连接数,Linux 受 Kernel sys.fs.file-max 限制
    # 修改: ulimit -SHn 65535
    worker_connections 10240;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;

    # Gzip
    gzip                on; # 开启 Gzip 压缩输出
    gzip_min_length     1k; # 设置允许压缩的页面最小字节数,页面字节数从header头得content-length中进行获取。默认值是0,不管页面多大都压缩。建议设置成大于2k的字节数,小于2k可能会越压越大。
    gzip_buffers 4      16k;# 设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流。 例如 4 4k 代表以4k为单位,按照原始数据大小以4k为单位的4倍申请内存。 4 8k 代表以8k为单位,按照原始数据大小以8k为单位的4倍申请内存。 如果没有设置,默认值是申请跟原始数据相同大小的内存空间去存储gzip压缩结果。
    gzip_http_version 1.0; # 压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
    gzip_comp_level 2; # 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间
    #gzip_types text/html
    gzip_types text/plain application/x-javascript text/css application/xml; # 压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
    gzip_disable "MSIE [1-6]\."; # E6及以下禁止压缩
    gzip_vary on; # 给CDN和代理服务器使用,针对相同url,可以根据头信息返回压缩和非压缩副本

    # Sendfile
    sendfile            on; # 是否调用 sendfile 函数传输文件,当磁盘 IO 压力大时可以适当关闭
    tcp_nopush          on; # 在 Linux/Unix 中优化 TCP 传输,依赖 sendfile 选项
    tcp_nodelay         on; # 将小包组成大包, 提高带宽利用率(Nagle 算法)
    autoindex off; # 开启列表访问,通常结合 fancyindex 美化目录样式
    keepalive_timeout   65; # 长连接超时时间
    types_hash_max_size 2048; # 影响散列表的冲突率,与内存占用成正比,当报错 "无法构建types_hash" 时酌情修改

    # 浏览器只识别 mime_type 来展示内容,Nginx 可以处理响应文件拓展名与 mime_type 之间的关联
    include             /etc/nginx/mime.types; # 引入 mime_type 关联表
    default_type        application/octet-stream; # 默认 mime_type 类型
    #charset utf-8; # 默认编码
    client_max_body_size 20M; # 请求体 Max 大小,通常用于上传文件大小限制

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /etc/nginx/conf.d/*.conf; # 引入外部配置文件,通常用于网站之间解耦合,即一个网站一个配置文件

    server {
        listen       80 default_server; # 监听端口,default 即请求 80 端口时默认匹配此 Server
        listen       [::]:80 default_server; # IPV6 监听
        server_name  _; # 监听域名/主机名
        root         /usr/share/nginx/html; # Server 主目录,在 location 没有匹配时会继续匹配此 Path 下的文件
        index index.html index.htm index.jsp; # 默认页面匹配
        #charset utf-8; # 编码

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf; # 引入一些默认配置

        upstream httpds { # 反向代理 Stream
            server 127.0.0.1:8080    weight=5  max_conns=800 max_fails=1  fail_timeout=20;
        }

        # location [ = | ~ | * | ^ ] uri { ... }
        # location URI {} 对当前路径及子路径下的所有对象都生效;
        # location = URI {} 注意URL最好为具体路径。 精确匹配指定的路径,不包括子路径,因此,只对当前资源生效;
        # location ~ URI {} location ~* URI {} 模式匹配URI,此处的URI可使用正则表达式,区分字符大小写,*不区分字符大小写;
        # location ^~ URI {} 禁用正则表达式
        # 优先级:= > ^~ > |* > /|/dir/
        location / {
            # IP 访问控制
            #deny  IP / IP段
            deny  172.16.9.5;
            allow 172.16.9.0/24;192.168.0.0/16;192.0.0.0/8

            # 用户 Auth
            # 生成用户配置文件并将 wars 用户追加: htpasswd -c -d /etc/nginx/conf.d/users wars
            auth_basic  "closed site"; # 登陆提示
            auth_basic_user_file /etc/nginx/conf.d/users; # 用户配置文件

            # Nginx 访问状态监控页面
            stub_status on;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }

        access_log  "pipe:rollback logs/host.access_log interval=1d baknum=7 maxsize=2G"  main;
    }
}

本文采用知识共享 署名-相同方式共享 4.0 国际 许可协议进行许可。
访问 https://creativecommons.org/licenses/by-sa/4.0/ 查看该许可协议。

1) LVS D-NAT 模型

发生 404 了

2) LVS DR 模型(多公网 IP)

发生 404 了

2.1) DR 模型搭建

2.1.0) 前言

DR 模型的关键在于,如何让 RealServer 持有 VIP,但是不向本机外通告持有该 VIP。
实现需要修改内核参数 arp_ignore、arp_announce,并在环回接口上虚拟 VIP。
将 arp_ignore 设置 1,不响应 VIP 的 arp 广播请求; arp_announce 设置 2,不向外通告拥有 VIP。

2.1.0.1) arp_ignore

0:只要本地配置有相应地址,就给予相应。
1:仅在请求到达的接口 MAC 地址匹配时,才给予响应。

2.1.0.2) arp_announce

0:将本地任何接口上任何地址向外通告。
1:试图仅向目标网络通告与其网络匹配的地址。
2:仅向与本地接口上地址匹配的网络进行通告。

2.1.1) 服务端机器 lvs-web-1 (10.9.6.11)

# 软件包准备并搭建一个 web 容器
yum install net-tools httpd -y
echo web-1 > /var/www/html/index.html
systemctl start httpd
systemctl enable httpd
# (注意,将 enp0s5 替换成相应的网卡)
echo 'net.ipv4.conf.enp0s5.arp_ignore = 1' | tee -a /etc/sysctl.conf
echo 'net.ipv4.conf.enp0s5.arp_announce = 2' | tee -a /etc/sysctl.conf
echo 'net.ipv4.conf.all.arp_ignore = 1' | tee -a /etc/sysctl.conf
echo 'net.ipv4.conf.all.arp_announce = 2' | tee -a /etc/sysctl.conf
sysctl -p
# 配置 VIP 到环回接口上
ifconfig lo:0 10.9.6.10 netmask 255.255.255.255

2.1.2) 服务端机器 lvs-web-2 (10.9.6.12)

# 软件包准备并搭建一个 web 容器
yum install net-tools httpd -y
echo web-2 > /var/www/html/index.html
systemctl start httpd
systemctl enable httpd
# (注意,将 enp0s5 替换成相应的网卡)
echo 'net.ipv4.conf.enp0s5.arp_ignore = 1' | tee -a /etc/sysctl.conf
echo 'net.ipv4.conf.enp0s5.arp_announce = 2' | tee -a /etc/sysctl.conf
echo 'net.ipv4.conf.all.arp_ignore = 1' | tee -a /etc/sysctl.conf
echo 'net.ipv4.conf.all.arp_announce = 2' | tee -a /etc/sysctl.conf
sysctl -p
# 配置 VIP 到环回接口上
ifconfig lo:0 10.9.6.10 netmask 255.255.255.255

2.1.3) 负载机器 lvs-main (10.9.6.3/10.9.6.10)

ipvsadm -A -t 10.9.6.10:80 -s rr
ipvsadm -a -t 10.9.6.10:80 -r 10.9.6.12 -g -w 1
ipvsadm -a -t 10.9.6.10:80 -r 10.9.6.11 -g -w 1

3) LVS DR 模型(单公网 IP)

发生 404 了

本文采用知识共享 署名-相同方式共享 4.0 国际 许可协议进行许可。
访问 https://creativecommons.org/licenses/by-sa/4.0/ 查看该许可协议。

1) OSI 七层参考模型

  1. 应用层
  2. 表示层
  3. 会话层
  4. 传输控制层
  5. 网络层
  6. 链路层
  7. 物理层

2) TCP/IP 四层精简模型

2.1) 应用层 (用户界面)

2.2) 传输层 (Port)

三次握手 -> 数据传输 -> 四次分手

2.3) 网络层 (IP)

基于路由表实现,Linux 查看路由表 route -n,基础路由表来源是 OS 中的网卡配置。
网络层就是找到下一跳,从上往下基于路由表每一条做匹配:目标 IP 与一条路由的掩码做与运算,与该条目 Destination 匹配则找了下一跳。

2.4) 链路层 (MAC)

链路层基于 MAC 地址,将含有目标 IP 的数据包再套上一层,链路层也有一张路由表,Linux 查看路由表 `arp -a
arp 会解释 IP 和网卡 MAC 地址的映射,受限与局域网,将数据包丢给下一个节点(下一跳、下一个 MAC 地址)

2.4.1) ARP 路由表来源

当机器刚开机时,ARP 表是空的,只有下一跳的 IP,那么数据包应该怎么发出去呢?即本机 ARP 缓存表中没有目标地址的缓存,将会经历一个 ARP 解析流程:

  1. 打包一个包含(源 IP、源 MAC、目标 IP、目标MAC 为 FF:FF:FF:FF:FF:FF) 的包,交换机收到 MAC 地址为 FF:FF:FF:FF:FF:FF 的包时会将此包广播给其他所有 Port
  2. 的目标机器收到包,若机器 IP 不匹配下一跳 IP,此包将被丢弃
  3. 若 IP 匹配,则向源 MAC 回包,包含匹配目标机器的 MAC
  4. 源机器将此记录添入 ARP 表
2.4.1.1) ARP 欺骗

这里会引入一个 ARP 欺骗的问题,若同时有两台机器向源机器回 ARP Response,源机器最终会记录最后一个收到的 ARP Response,这就引发了 ARP 欺骗

2.5) TCP/IP 总结

从物理层开始,每一层都向上层提供服务访问点。
在连接因特网的普通微机上:

  • 物理层:服务访问点就是网卡接口 (RJ45接口或BNC接口)
  • 数据链路层:服务访问点是 MAC 地址
  • 网络层的服务访问点是 IP 地址
  • 传输层的服务访问点是 Port 端口号
  • 应用层提供的服务访问点是用户界面

3) Linux 命令行打开网站(不使用 CURL)

# 进入当前进程的文件描述符目录,0(stdin),1(stdout)和2(stderr)
cd /proc/$$/fd
# 创建一个 TCP Socket 输入输出链接文件 8,链接到百度
exec 8<> /dev/tcp/www.baidu.com/80
# 管道加 & 的意思代表 8 时文件描述符非文件
echo -e 'GET / HTTP/1.0\n' >& 8
# 将 8 的输出管道到 stdin
cat 0 <& 8

9) 参见

本文采用知识共享 署名-相同方式共享 4.0 国际 许可协议进行许可。
访问 https://creativecommons.org/licenses/by-sa/4.0/ 查看该许可协议。

限制 rsync 对缓存的占用问题

1) 服务端限制

1.1) 停掉已经运行的 rsync 服务端

1.2) 创建一个 cgroup

cgcreate -g memory:rsynclimit

1.3) 限制其内存使用为 2000M

cgset -r memory.limit_in_bytes=2000M rsynclimit

1.4) 在 cgroup 中执行 rsync --daemon

cgexec -g memory:rsynclimit rsync --daemon

2) 客户端限制

2.1) 创建一个 cgroup

cgcreate -g memory:rsynclimit

2.2) 限制其内存使用为 2000M

cgset -r memory.limit_in_bytes=2000M rsynclimit

2.3) 在 cgroup 中执行 rsync 客户端操作

cgexec -g memory:rsynclimit rsync

本文采用知识共享 署名-相同方式共享 4.0 国际 许可协议进行许可。
访问 https://creativecommons.org/licenses/by-sa/4.0/ 查看该许可协议。

最近不知道为啥 OpenWrt 多播炸了,公司内网单线限速太慢。
想切手机热点,又有访问内网服务的需求,就可以用简单路由表实现:

sudo route delete 0.0.0.0 # Remote 掉默认路由
sudo route add -net 0.0.0.0 172.20.10.1 # 默认路由设成外网网卡设备网关
sudo route add 172.16.6.0/24 192.168.1.1 # 公司内网地址指向内网网卡网关
sudo route add 172.16.7.0/24 192.168.1.1 # 公司内网地址指向内网网卡网关

完成,MacOS 记得把 Network 管理中,Set Service Order 里设置成外网网卡优先
完毕。

[Meting]
[Music title="盗将行(翻自 花粥)" author="须臾aow/花世" url="https://mirrors.wars.cat/files/djx.mp3" pic="https://blog.wars.cat/usr/themes/moeka/img/warscat.jpg" lrc="https://mirrors.wars.cat/files/djx.lrc"/]
[/Meting]

Title - Artist
0:00