文章目录
1.编写playbook实现nginx的安装过程,通过变量的方式传入
环境:三台centos主机10.0.0.3为ansible-server 10.0.0.4与10.0.0.6为客户端
centos8安装ansible
bash
[root@ansible-server ~]# vim ansible.sh
#!/bin/bash
cat > /etc/yum.repos.d/epel.repo < EOF
[epel]
name=epel
baseurl=https://mirrors.aliyun.com/epel/8/Everything/x86_64/
gpgcheck=0
enabled=1
EOF
yum clean all && yum makecache
yum install python39 -y
pip-3.9 install ansible
mkdir -p /etc/ansible
cat > /etc/ansible/ansible.cfg < EOF
[defaults]
inventory=/etc/ansible/hosts
EOF
cat > /etc/ansible/hosts < EOF
[websrvs]
10.0.0.4
10.0.0.6
EOF
[root@ansible-server ~]# chmod +x ansible.sh
[root@ansible-server ~]# bash ansible.sh
[root@ansible-server ~]# ssh-keygen
[root@ansible-server ~]# ssh-copy-id 10.0.0.4
[root@ansible-server ~]# ssh-copy-id 10.0.0.6
编写playbook第一种基于yum安装
bash
[root@ansible-server ~]# cat install_nginx.yml
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: create group nginx
group: name=nginx state=present
- name: create user nginx
user: name=nginx group=nginx state=present
- name: Install Nginx
yum: name=nginx state=present
- name: Start Nginx
service: name=nginx state=started enabled=yes
[root@ansible-server ~]# ansible-playbook install_nginx.yml
第二种基于编译安装
bash
[root@ansible-server ~]# cat install_nginx.yml
---
- hosts: websrvs
remote_user: root
gather_facts: yes
vars:
nginx_version: 1.22.1 #定义安装版本号
nginx_file: nginx-{{ nginx_version }}.tar.gz
nginx_dir: nginx-{{ nginx_version }}
user: nginx #定义用户变量
group: nginx #定义group变量
cpu: "{{ ansible_processor_vcpus }}" #获取CPU核数
install_dir: webserver
tasks:
- name: 安装依赖包
yum: name=gcc,make,gcc,gcc-c++,wget,pcre-devel,openssl-devel,zlib-devel
- name: create group {{ group }}
group: name={{ group }}
- name: create user {{ user }}
user: name={{ user }} group={{ group }} shell=/sbin/nologin system=yes create_home=no
- name: 下载nginx并进行解压缩
unarchive: src=https://nginx.org/download/{{nginx_file}} dest=/usr/local/src owner=root group=root copy=no
- name: 创建安装目录
file: path=/data/{{ install_dir }} recurse=yes state=directory
- name: 进入nginx目录进行编译并安装
shell: chdir=/usr/local/src/{{ nginx_dir }} ./configure --prefix=/data/{{ install_dir }} --without-http_rewrite_module --without-http_gzip_module --user={{ user }} --group={{ group }} --pid-path=/data/{{ install_dir }}/run/nginx.pid --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module && make -j {{ cpu }} && make install
- name: 授权
shell: chown -R nginx.nginx /data/{{ install_dir }}
- name: 创建软连接
file: src=/data/{{ install_dir }}/sbin/nginx dest=/usr/sbin/ state=link
- name: 创建server文件
shell: /usr/bin/echo -e "[Unit]\n Description=The nginx HTTP and reverse proxy server\n After=network.target remote-fs.target nss-lookup.target\n [Service]\n Type=forking\n PIDFile=/data/{{ install_dir }}/run/nginx.pid\n ExecStartPre=/usr/bin/rm -f /data/{{ install_dir }}/run/nginx.pid\n ExecStartPre=/usr/sbin/nginx -t\n ExecStart=/usr/sbin/nginx\n ExecReload=/bin/kill -s HUP $MAINPID\n KillSignal=SIGQUIT\n TimeoutStopSec=5\n KillMode=mixed\n PrivateTmp=true\n [Install]\n WantedBy=multi-user.target\n" > /usr/lib/systemd/system/nginx.service
- name: 加载文件
shell: systemctl daemon-reload
- name: 启动服务
service: name={{ user }} state=started enabled=yes
[root@ansible-server ~]# ansible-playbook install_nginx.yml
第三种基于角色的形式进行安装
bash
[root@ansible-server ~]# mkdir -pv /etc/ansible/roles/nginx{tasks,vars}
[root@ansible-server ~]# tree /etc/ansible/roles/
roles/
└── nginx
├── tasks
│ ├── chown.yml
│ ├── code.yml
│ ├── download.yml
│ ├── group.yml
│ ├── link.yml
│ ├── main.yml
│ ├── mkdir.yml
│ ├── service_conf.yml
│ ├── service.yml
│ ├── user.yml
│ └── yum.yml
└── vars
└── main.yml
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/tasks/yum.yml
- name: 安装依赖包
yum: name=gcc,make,gcc,gcc-c++,wget,pcre-devel,openssl-devel,zlib-devel
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/tasks/user.yml
- name: create user {{ user }}
user: name={{ user }} group={{ group }} shell=/sbin/nologin system=yes create_home=no
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/tasks/group.yml
- name: create group {{ group }}
group: name={{ group }}
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/tasks/chown.yml
- name: 授权
shell: chown -R nginx.nginx /data/{{ install_dir }}
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/tasks/code.yml
- name: 进入nginx目录进行编译并安装
shell: chdir=/usr/local/src/{{ nginx_dir }} ./configure --prefix=/data/{{ install_dir }} --without-http_rewrite_module --without-http_gzip_module --user={{ user }} --group={{ group }} --pid-path=/data/{{ install_dir }}/run/nginx.pid --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module && make -j {{ cpu }} && make install
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/tasks/download.yml
- name: 下载nginx并进行解压缩
unarchive: src=https://nginx.org/download/{{nginx_file}} dest=/usr/local/src owner=root group=root copy=no
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/tasks/link.yml
- name: 创建软连接
file: src=/data/{{ install_dir }}/sbin/nginx dest=/usr/sbin/ state=link
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/tasks/mkdir.yml
- name: 创建安装目录
file: path=/data/{{ install_dir }} recurse=yes state=directory
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/tasks/service_conf.yml
- name: 创建server文件
shell: /usr/bin/echo -e "[Unit]\n Description=The nginx HTTP and reverse proxy server\n After=network.target remote-fs.target nss-lookup.target\n [Service]\n Type=forking\n PIDFile=/data/{{ install_dir }}/run/nginx.pid\n ExecStartPre=/usr/bin/rm -f /data/{{ install_dir }}/run/nginx.pid\n ExecStartPre=/usr/sbin/nginx -t\n ExecStart=/usr/sbin/nginx\n ExecReload=/bin/kill -s HUP $MAINPID\n KillSignal=SIGQUIT\n TimeoutStopSec=5\n KillMode=mixed\n PrivateTmp=true\n [Install]\n WantedBy=multi-user.target\n" > /usr/lib/systemd/system/nginx.service
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/tasks/service.yml
- name: 加载文件
shell: systemctl daemon-reload
- name: 启动服务
service: name={{ user }} state=started enabled=yes
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/tasks/main.yml
- include: user.yml
- include: group.yml
- include: download.yml
- include: mkdir.yml
- include: code.yml
- include: chown.yml
- include: link.yml
- include: service_conf.yml
- include: service.yml
[root@ansible-server ~]# vim /etc/ansible/roles/nginx/vars/main.yml
nginx_version: 1.22.1 #定义安装版本号
nginx_file: nginx-{{ nginx_version }}.tar.gz
nginx_dir: nginx-{{ nginx_version }}
user: nginx #定义用户变量
group: nginx #定义group变量
cpu: "{{ ansible_processor_vcpus }}" #获取CPU核数
install_dir: webserver
[root@ansible-server ~]# vim /etc/ansible/nginx.yml
---
- hosts: websrvs
remote_user: root
gather_facts: yes
roles:
- nginx
#执行ansible-playbook
[root@ansible-server ~]# ansible-playbook /etc/ansible/nginx.yml
2.http协议版本和工作原理
HTTP版本
版本 | 特性 |
---|---|
http0.9 | 原型版本,功能简陋,只有一个命令GET。服务器只能回应HTML格式字符串,不能回应别的格式。 |
http1.0 | 支持cache, MIME, method每个TCP连接只能发送一个请求,发送数据完毕,连接就关闭,如果还要请求其他资源,就必须再新建一个连接引入了POST命令和HEAD命令头信息是 ASCII 码,后面数据可为任何格式。服务器回应时会告诉客户端,数据是什么格式,即Content-Type字段的作用。常见Content-Type值:text/xml image/jpeg audio/mp3 |
http1.1 | 引入了持久连接,即TCP连接默认不关闭,可以被多个请求复用,不用声明Connection: keep-alive。对于同一个域名,大多数浏览器允许同时建立6个持久连接引入了管道机制,即在同一个TCP连接里,客户端可以同时发送多个请求,进一步改进了HTTP协议的效率新增方法:PUT、PATCH、OPTIONS、DELETE同一个TCP连接里,所有的数据通信是按次序进行的。服务器只能顺序处理回应,前面的回应慢,会有许多请求排队,造成"队头堵塞"(Head-of-line blocking)为避免上述问题,两种方法:一是减少请求数,二是同时多开持久连接。网页优化技巧,如合并脚本和样式表、将图片嵌入CSS代码、域名分片(domain sharding)等HTTP 协议不带有状态,每次请求都必须附上所有信息。请求的很多字段都是重复的,浪费带宽,影响速度。 |
HTTP原理
- 建立连接:客户端通过TCP/IP协议与服务器进行连接,服务器接收或拒绝连接请求。
- 接受请求:客户端向服务器发送HTTP请求。请求由请求行、请求头和请求体(可选)组成。请求行包含请求方法(如GET、POST等)、请求的URI和HTTP协议版本。请求头包含了一系列描述请求属性的信息,如客户端类型(User-Agent)、请求来源(Referer)、等。请求体(如果有)包含了要发送给服务器的数据,如表单数据、文件内容等。
- 服务器处理请求:服务器接收到客户端的请求后,会根据请求行中的URI和请求方法进行处理。
- 访问资源:服务器获取请求报文中请求的资源web服务器,即存放了web资源的服务器,负责向请求者提供对方请求的静态资源,或动态运行后生成的资源,服务器可能需要读取数据库、执行业务逻辑等,以生成响应数据。
- 构建响应报文:一旦Web服务器识别除了资源,就执行请求方法中描述的动作,并返回响应报文。响应报文中包含有响应状态码、响应首部,如果生成了响应主体的话,还包括响应主体。
(1)响应实体:如果事务处理产生了响应主体,就将内容放在响应报文中回送过去。响应报文中通常包 括:描述了响应主体MIME类型的Content-Type首部 描述了响应主体长度的Content-Length 实际报文的主体内容
( 2)URL重定向:web服务构建的响应并非客户端请求的资源,而是资源另外一个访问路径
( 3)MIME类型:Web服务器要负责确定响应主体的MIME类型。 - 发送响应报文:服务器将构建好的响应报文通过TCP连接发送回客户端。
- 记录日志:最后,当事务结束时,Web服务器会在日志文件中添加一个条目,来描述已执行的事务。
3.IO模型和零复制技术的原理
IO模型
- 阻塞IO模型,用户线程在内核进行IO操作时被阻塞用户线程通过系统调用read发起I/O读操作,由用户空间转到内核空间。内核等到数据包到达后,然后将接收的数据拷贝到用户空间,完成read操作用户需要等待read将数据读取到buffer后,才继续处理接收的数据。
- 非阻塞IO模型:用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据到达后,才真正读取到数据,继续执行。
- 多路复用IO模型主要包括:select,poll,epoll三种系统调用,select/poll/epoll的好处就在于单个process就可以同时处理多个网络连接的IO。它的基本原理select/poll/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程。当用户进程调用了select,那么整个进程会被block,而同时,kernel会"监视"所有select负责的socket,当任何一个socket中的数据准备好了,select就会返回。这个时候用户进程再调用read操作,将数据从kernel拷贝到用户进程。
- 信号驱动I/O模型:意思就是进程现在不用傻等着,也不用去轮询。而是让内核在数据就绪时,发送信号通知进程。调用的步骤是,通过系统调用 sigaction并注册一个信号处理的回调函数,该调用会立即返回,然后主程序可以继续向下执行,当有I/O操作准备就绪,即内核数据就绪时,内核会为该进程产生一个SIGIO信号,并回调注册的信号回调函数,这样就可以在信号回调函数中系统调用 recvfrom获取数据,将用户进程所需要的数据从内核空间拷贝到用户空间。
- 异步I/O模型:异步I/O 与 信号驱动I/O最大区别在于,信号驱动是内核通知用户进程何时开始一个I/O操作,而异步I/O是由内核通知用户进程I/O操作何时完成。相对于同步I/O,异步I/O不是顺序执行。
零复制原理
减少CPU拷贝 :在传统的IO操作中,数据通常需要从磁盘拷贝到内核缓冲区,然后再从内核缓冲区拷贝到用户空间。而零复制技术通过减少这些拷贝步骤来节省CPU资源。
减少上下文切换 :上下文切换是进程从用户态切换到内核态(或反之)的过程,每次系统调用都会引发上下文切换。零复制技术通过减少系统调用的次数来减少上下文切换的次数。
实现方式 :
sendfile :Nginx在Linux系统中通过sendfile系统调用来实现零复制。sendfile可以直接将内核缓冲区的数据发送到网络,而无需先拷贝到用户空间。
mmap:另一种实现方式是使用mmap技术,将文件映射到用户空间的内存地址上,然后通过网络发送这部分内存的数据。但Nginx通常更倾向于使用sendfile,因为它更简单且性能更好。