Nginx-编译安装

回顾

上一节中,我们讲了[ https://slcnx.github.io/2022/06/12/vmware%E5%AE%89%E8%A3%85%E7%B3%BB%E7%BB%9F/ ], vmware安装规划中,如何单机部署, 高可用部署。 本节讲讲其中一个小服务nginx,nginx用来提供公司网页的,基于用户体验的过程的原理如下:

image-20220708133818176

这里电脑从输入www.baidu.com到查看到百度,这一个过程中,需要本地计算机**浏览器**发起http请求,请求支持http协议的**web服务器**,拿到http响应。http协议规范定义了**请求和响应**的格式,[ https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Messages ], 而http协议是一种规范其实现是具体的软件,其客户端软件, 图形界面的浏览器(chrome, 360, firefox),命令行的curl命令。而服务端软件有httpd, nginx

我们在上一节中使用nginx作为静态站点,而没有使用apache的httpd,其原因就需要对比这两个软件的区别了。

nginx和apache的区别

请求到达服务器处理

Nginx IO模型

参考: [ https://www.modb.pro/db/401325 ]

浏览器请求到Linux服务器,基于请求的端口到达用户空间的进程,进程处理http协议的请求,基于URI解析协议, 域名,路径。从而找到对应的处理请求的配置,再加载合适的文件或代理到合适的后端应用服务器。

  • 动态请求,基于相应的协议获取数据。
  • 静态请求,需要读磁盘上的文件,就需要发起系统调用,内核加载数据到内核空间,进程从内核空间将数据拷贝到用户空间。这个是一次文件IO

请求到达用户空间的web进程的几种方式

  • 阻塞式IO

    • 请求数据未完全被内核加载到缓冲区时,进程是阻塞的。进程不占用CPU,并在等待队列中。直到数据加载完成,一次中断事件让内核把等待队列中的进程唤醒到达运行队列,这个时间进程才拿到数据,进行处理数据。
    • 一个进程处理一个请求
  • 非阻塞IO

    • 进程调用函数时,只要未加载完成,就返回error。未加载完成就不是error, 处理数据。下面是模拟的代码,不是error处理数据,是error会做完其他事后再循环,浪费大量CPU进行查看数据是否完成。

      1
      2
      3
      4
      5
      6
      while true; do 
      if [ `read` !== “error" ]; then
      #处理数据
      fi
      # 做其他事
      done

由于阻塞式IO不能处理多个请求,所以有了IO多路复用,专用于处理多个请求,io多路复用,支持select/poll/epoll。

  • select
    • 很多系统均支持
    • 进程调用select之后,就和非阻塞IO一样,立即知道有没有数据。没有数据做其他的事。有数据就下一次问select时就拿到数据加载数据到内存,进行后续处理。
    • select就可以维护多个连接,使用一个数组,要知道数组中哪个连接有新的数据来,需要遍历一次数组,时间复杂度是O(n)。
    • select默认的连接上限1024
  • poll
    • windows不支持
    • 维护多个连接是链表,没有连接上限。知道哪个连接有数据来是遍历,时间复杂 度是O(n)
  • epoll
    • 进程调用epoll之后,会注册一个信号,这个信号函数会有后续的处理,所以当数据准备好之后,就调用进程的后续函数进行加载数据到用户空间的内存,再处理。
    • 维护连接是hash表,知道哪个连接有数据来是遍历,时间复杂 度是O(1)。

以上5种IO模型,在内核准备数据时进程除了第1个均是非阻塞,非阻塞中除了epoll 信号驱动之外均是同步,即进程轮轮循查看数据是否就绪。在数据准备好之后,均由各自函数加载数据到用户空间,进行处理。

网络&操作系统-linux五种IO模型| 池元烨的博客

引用自: [ http://chiyuanye.com/2019/02/25/five-IO-models.html ]

aio_read这个函数是异步的,内核准备数据,数据加载到用户空间进程内存,均由内核完成,完成之后通知进程。进程进行后续操作。

区别

apache有2.2和2.4 这2个版本。均有3个处理模块,( prefork, work, event )。

  • apache
    • prefork, select IO模型
    • work, poll IO模型
    • event, event IO模型
  • nginx
    • aio_read

nignx特点: 异步非阻塞IO解决C10K问题(10K Connections),且是免费的、开源的、⾼性能的HTTP服务器HTTP反向代理服务器邮件代理服务器、以及TCP/UDP代理服务器

Nginx的优势在于:反向代理,静态资源Web服务,rewrite规则,稳定性, 模块化设计,静态文件处理,内存消耗,节省带宽,稳定性高,支持热部署,可以高并发连接等优点。

Netcraft公司于1994年底在英国成⽴,多年来⼀直致⼒于互联⽹市场以及在线安全⽅⾯的咨询服务,其中在国际上最具影响⼒的当属其针对⽹站服务器,域名解析/主机提供商,以及SSL市场所做的客观严谨的分析研究。

[ https://news.netcraft.com/ ] nginx 自19起始稳居第1。而之前一直是apache占主导地位。

image-20220708165429539

引用自: [ https://zhangzhuo.ltd/articles/2021/05/17/1621240754222.html ]

nginx介绍

模块化设计,较好的扩展性 高可靠性 支持热部署:不停机更新配置⽂件,升级版本,更换⽇志⽂件 低内存消耗:10000个keep-alive连接模式下的⾮活动连接,仅需2.5M内存 event-driven,aio,mmapsendfile

image-20220708172129010

mmap要比普通的read系统调用少了一次copy的过程。因为read调用,进程是无法直接访问kernel space的,所以在read系统调用返回前,内核需要将数据从内核复制到进程指定的buffer。但mmap之后,进程可以直接访问mmap的数据(page cache)。第2个阶段 kernel > user space不需要了。

引用自: [ https://blog.csdn.net/universsky2015/article/details/115114706 ]

作为web服务器的时候打开sendfile加快静态⽂件传输,指定是否使⽤sendfile系统调⽤来传输⽂件,sendfile通过DMA(直接内存访问)⽅式直接访问⽂件数据,并通过传输协议发送,从⽽避免了数据在内核缓冲区和⽤户缓冲区之间的拷⻉,操作效率很⾼,被称之为零拷⻉,从硬盘>kernel>user space封装>kernel>协议栈,直接到: 硬盘>> kernel buffer (快速拷⻉到kernel socket buffer) >>协议栈。

环境初始化

  1. 准备nginx主机

  2. 实验归划

    image-20220708210648579

    IP 主机名 用途 备注
    172.16.100.100 template-centos.magedu.com 模板机
    172.16.100.101 nginx-1.magedu.com
    172.16.100.102 nginx-2.magedu.com
    172.16.100.103 nginx-3.magedu.com
    172.16.100.104 nginx-4.magedu.com
    172.16.100.105 nginx-5.magedu.com
    172.16.100.106 nginx-6.magedu.com
    172.16.100.107 nginx-7.magedu.com
    172.16.100.108 nginx-8.magedu.com
    172.16.100.109 nginx-9.magedu.com
    172.16.100.110 nginx-10.magedu.com
    172.16.100.111 php-1.magedu.com
    172.16.100.112 php-2.magedu.com
    172.16.100.113 php-3.magedu.com
    172.16.100.114 php-4.magedu.com
    172.16.100.115 php-5.magedu.com
    172.16.100.116 php-6.magedu.com
    172.16.100.117 php-7.magedu.com
    172.16.100.118 php-8.magedu.com
    172.16.100.119 php-9.magedu.com
    172.16.100.120 php-10.magedu.com
    172.16.100.121 mysql-1.magedu.com
    172.16.100.122 mysql-2.magedu.com
    172.16.100.123 mysql-3.magedu.com
    172.16.100.124 mysql-4.magedu.com
    172.16.100.125 mysql-5.magedu.com
    172.16.100.126 mysql-6.magedu.com
    172.16.100.127 mysql-7.magedu.com
    172.16.100.128 mysql-8.magedu.com
    172.16.100.129 mysql-9.magedu.com
    172.16.100.130 mysql-10.magedu.com
  3. 准备网络, vmnet9, 172.16.0.0/16 网络。

  4. 克隆 最初,调整配置,快照初始,准备模板主机

  5. 初始化主机为模板主机。

    1
    bash init.sh --resourceslimit=1 --kernelparams=1 --basepkgs=1 --chinese=0  --eth0=1 --umirror=0    --port=6655 --allow-root-login=yes --allow-pass-login=yes --root-password='#^DzGp)DIN+1M)'  --hostname=template-centos.magedu.com --ipaddr=172.16.100.100 --netmask=255.255.0.0 --gateway=172.16.100.2 --dns=223.6.6.6 --author=songliangcheng --qq=2192383945 --desc="A test toy"
    1
    2
    rm -f /etc/sysconfig/network-scripts/ifcfg-ens33
    reboot
  6. 修改网络

  7. 准备网关

    1
    2
    3
    4
    5
    6
    7
    #准备网关,172.16.0.2
    TYPE=Ethernet
    BOOTPROTO=static
    DEVICE=eth1
    ONBOOT=yes
    IPADDR=172.16.0.2
    NETMASK=255.255.0.0
    1
    2
    sysctl -w net.ipv4.ip_forward=1
    iptables -t nat -I POSTROUTING -s 172.16.0.0/16 -o eth0 -j MASQUERADE

    现在ping www.baidu.com

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    # 本机看到
    [root@template-centos ~]# tcpdump -nn -vv -i eth0 icmp
    tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
    20:22:32.070572 IP (tos 0x0, ttl 64, id 18283, offset 0, flags [DF], proto ICMP (1), length 84)
    172.16.100.100 > 110.242.68.4: ICMP echo request, id 1485, seq 28, length 64
    20:22:32.113527 IP (tos 0x0, ttl 127, id 30763, offset 0, flags [none], proto ICMP (1), length 84)
    110.242.68.4 > 172.16.100.100: ICMP echo reply, id 1485, seq 28, length 64

    # 网关看到
    192.168.131.100 > 110.242.68.4: ICMP echo request, id 1485, seq 62, length 64
    20:23:06.167984 IP (tos 0x0, ttl 128, id 30800, offset 0, flags [none], proto ICMP (1), length 84)
    110.242.68.4 > 192.168.131.100: ICMP echo reply, id 1485, seq 62, length 64

    172.16.100.100 -> 192.168.131.100 -> 110.242.68.4 (修改源为网关的可以出去的IP)

    172.16.100.100 <- 192.168.131.100 <- 110.242.68.4 ( 修改目标为内网IP)

  8. 重启验证ip, 域名解析, kernel params, crontab, ssh, alias

  9. 关机快照。template,

    1
    2
    3
    6655
    root
    #^DzGp)DIN+1M)

准备第1个节点

1
2
3
bash init.sh --hostname=nginx-1.magedu.com --ipaddr=172.16.100.101 --netmask=255.255.0.0 --gateway=172.16.100.2 --dns=223.6.6.6 --root-password='7HmqYhjwvNBuYW2X'
reboot
验证ip,网络, 主机名

编译安装nginx

https://nginx.org/en/download.html

Stable version nginx-1.22.0

制作rpm

进入nginx的源码仓库: [ http://nginx.org/packages/centos/7Server/SRPMS/ ]

下载安装geoip

1
2
3
wget http://nginx.org/packages/centos/7Server/SRPMS/nginx-module-geoip-1.22.0-1.el7.ngx.src.rpm

rpm -ivh nginx-module-geoip-1.22.0-1.el7.ngx.src.rpm

准备yum-utils

1
yum install yum-utils rpm-build -y

构建rpm包

1
2
3
4
5
6
cd /root/rpmbuild/SPECS
# 安装依赖的模板
# yum-builddep nginx-module-geoip.spec --downloadonly --downloaddir=/root/pkgs
# ls /root/pkgs/ | xargs -I {} echo {} | sed 's@-[0-9].*@@' | xargs
cpp e2fsprogs e2fsprogs-libs gcc GeoIP GeoIP-devel geoipupdate glibc glibc-common glibc-devel glibc-headers kernel-headers keyutils-libs-devel krb5-devel krb5-libs libcom_err libcom_err-devel libgcc libgomp libkadm5 libmpc libselinux libselinux-devel libselinux-python libselinux-utils libsepol-devel libss libverto-devel mpfr openssl openssl-devel openssl-libs pcre2 pcre2-devel pcre2-utf16 pcre2-utf32 pcre-devel zlib zlib-devel

rpmbuild -bb nginx-module-geoip.spec

# rpm
   [root@localhost SPECS]# ls ../RPMS/x86_64/
    nginx-module-geoip-1.22.0-1.el7.ngx.x86_64.rpm  nginx-module-geoip-debuginfo-1.22.0-1.el7.ngx.x86_64.rpm
rpmbuild -bb nginx

得到依赖

1
cpp e2fsprogs e2fsprogs-libs gcc GeoIP GeoIP-devel geoipupdate glibc glibc-common glibc-devel glibc-headers kernel-headers keyutils-libs-devel krb5-devel krb5-libs libcom_err libcom_err-devel libgcc libgomp libkadm5 libmpc libselinux libselinux-devel libselinux-python libselinux-utils libsepol-devel libss libverto-devel mpfr openssl openssl-devel openssl-libs pcre2 pcre2-devel pcre2-utf16 pcre2-utf32 pcre-devel zlib zlib-devel

安装rpm之后得到编译参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@localhost SPECS]# rpm -ivh ../RPMS/x86_64/nginx-1.22.0-1.el7.ngx.x86_64.rpm 
准备中... ################################# [100%]
正在升级/安装...
1:nginx-1:1.22.0-1.el7.ngx ################################# [100%]
----------------------------------------------------------------------

Thanks for using nginx!

Please find the official documentation for nginx here:
* https://nginx.org/en/docs/

Please subscribe to nginx-announce mailing list to get
the most important news about nginx:
* https://nginx.org/en/support.html

Commercial subscriptions for nginx are available on:
* https://nginx.com/products/
1
2
3
4
5
6
[root@localhost SPECS]# nginx -V
nginx version: nginx/1.22.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC)
built with OpenSSL 1.0.2k-fips 26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

抽取部分

1
./configure --prefix=/apps/nginx    --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module  --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module  --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_geoip_module=dynamic --with-stream_geoip_module=dynamic

编译安装 (ubuntu/centos均可)

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@nginx-2 ~]# tar xvf nginx-1.22.0.tar.gz -C /usr/local/src/

yum install cpp e2fsprogs e2fsprogs-libs gcc GeoIP GeoIP-devel geoipupdate glibc glibc-common glibc-devel glibc-headers kernel-headers keyutils-libs-devel krb5-devel krb5-libs libcom_err libcom_err-devel libgcc libgomp libkadm5 libmpc libselinux libselinux-devel libselinux-python libselinux-utils libsepol-devel libss libverto-devel mpfr openssl openssl-devel openssl-libs pcre2 pcre2-devel pcre2-utf16 pcre2-utf32 pcre-devel zlib zlib-devel -y

./configure --prefix=/apps/nginx \
--user=nginx --group=nginx \
--with-compat --with-file-aio --with-threads \
--with-http_addition_module --with-http_auth_request_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module \
--with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module \
--with-http_stub_status_module --with-http_sub_module --with-http_v2_module \
--with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module \
--with-http_geoip_module=dynamic --with-stream_geoip_module=dynamic

你将看到以下输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Configuration summary
+ using threads
+ using system PCRE2 library
+ using system OpenSSL library
+ using system zlib library

nginx path prefix: "/apps/nginx"
nginx binary file: "/apps/nginx/sbin/nginx"
nginx modules path: "/apps/nginx/modules"
nginx configuration prefix: "/apps/nginx/conf"
nginx configuration file: "/apps/nginx/conf/nginx.conf"
nginx pid file: "/apps/nginx/logs/nginx.pid"
nginx error log file: "/apps/nginx/logs/error.log"
nginx http access log file: "/apps/nginx/logs/access.log"
nginx http client request body temporary files: "client_body_temp"
nginx http proxy temporary files: "proxy_temp"
nginx http fastcgi temporary files: "fastcgi_temp"
nginx http uwsgi temporary files: "uwsgi_temp"
nginx http scgi temporary files: "scgi_temp"

之后,编译安装

1
make -j $(nproc) && make install -j $(nproc)
1
2
3
4
5
[root@nginx-2 nginx-1.22.0]# cd /apps/nginx/
[root@nginx-2 nginx]# groupadd -g 2022 nginx
[root@nginx-2 nginx]# useradd -u 2022 -s /sbin/nologin nginx -g nginx

[root@nginx-2 nginx]# ./sbin/nginx -g 'daemon off;' # 需要在前台

浏览器访问 http://172.16.100.102/

image-20220708214528854

ctrl c 终止后,准备服务脚本

1
2
3
4
5
6
7
8
# 为当前nginx添加版本方便升级nginx, 回退
mv /apps/nginx/ /apps/nginx-1.22.0

# 自动生成服务脚本 github
curl -L https://raw.githubusercontent.com/slcnx/post-precompile/main/post-precompile.sh | bash -s -- -ap /apps/nginx-1.22.0 -s "./sbin/nginx -g 'daemon off;'"

# 自动生成服务脚本 gitee
curl -L https://gitee.com/slcnx/post-precompile/raw/master/post-precompile.sh | sed 's/\r//' | bash -s -- -ap /apps/nginx-1.22.0 -s "./sbin/nginx -g 'daemon off;'"

添加模块

echo模块

编译方法: [ https://github.com/openresty/echo-nginx-module#installation ]

下载包: [ https://github.com/openresty/echo-nginx-module/releases/tag/v0.62 ]

基于以上的编译二次编译

1
2
3
4
5
6
7
8
9
./configure  --prefix=/apps/nginx --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_geoip_module=dynamic --with-stream_geoip_module=dynamic --add-module=/usr/local/src/echo-nginx-module-0.62/


make -j $(nproc) && make install -j $(nproc)


nginx -V

systemctl restart nginx

ssl模块

引用自: [ https://www.cnblogs.com/Oejfr/p/14902721.html ]

1
wget https://www.openssl.org/source/openssl-3.0.5.tar.gz
1
2
3
4
5
6
7
./configure  --prefix=/apps/nginx --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-http_geoip_module=dynamic --with-stream_geoip_module=dynamic  --with-openssl=/root/openssl-3.0.5

make -j $(nproc) && make install -j $(nproc)

nginx -V

systemctl restart nginx

作业

  1. 独立完成nginx yum安装,apt安装。
  2. 独立完成nginx制作rpm,添加echo模块,升级ssl,同时制作rpm。
  3. 独立完成nginx编译安装,添加echo模块,升级ssl。

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!