常规的web服务器一般提供对于静态资源的访问,比如说:图片、web样式
网站提供的大部分交互功能都需要web编程语言的支持,而web服务对于程序的调用,不管编译型语言还是解释型语言,web服务同将对于应用程序的调用递交给通用网关接口(CGI)。CGI 服务完成对于程序的调用和运行,并将运行结构通过CGI接口返回给web服务,由web服务生成响应报文。
此时在web服务的领域内,引入了LAMP等较为知名的web架构,使web页面提供应用服务成为一种可能,
随着web网站的发展,基本的web服务器容易出现性能瓶颈、响应缓慢等问题,为了解决这些问题,人们尝试通过一些技术手段解决这个问题,这一类技术都属于负载均衡技术,常用于进行负载均衡的服务有:HAProxy、Nginx、lvs等。除此之外,还可以结合dns负载均衡等技术,即一个域名映射多个IP地址等方式。
nginx 负载均衡实验过程整理如下:
[root@bogon ~]# systemctl disable --now httpd // 确保80端口未被httpd 占用
[root@bogon ~]# systemctl start nginx.service // 启动nginx 服务
[root@bogon ~]# ps -elf | grep nginx
1 S root 5825 1 0 80 0 - 2875 sigsus 14:47 ? 00:00:00 nginx: master process /usr/sbin/nginx
5 S nginx 5826 5825 0 80 0 - 3964 ep_pol 14:47 ? 00:00:00 nginx: worker process
5 S nginx 5827 5825 0 80 0 - 3964 ep_pol 14:47 ? 00:00:00 nginx: worker process
0 S root 5833 2362 0 80 0 - 55417 pipe_r 14:47 pts/0 00:00:00 grep --color=auto nginx
// 恢复成默认的主配置文件,如果之前没有备份,可以使用在/etc/nginx/nginx.default 来恢复,略有不同,影响不大
[root@bogon ~]# cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf_$(date +%s) //备份当前配置文件
[root@bogon ~]# cp /etc/nginx/nginx.conf_1724661958 /etc/nginx/nginx.conf // 恢复默认配置0
cp: overwrite '/etc/nginx/nginx.conf'? y
[root@bogon ~]# vim /etc/nginx/nginx.conf // 暂时无需修改,额外的配置放在conf.d 目录下
[root@bogon ~]# ls /etc/nginx/conf.d/
[root@bogon ~]# vim /etc/nginx/conf.d/real_web.conf // 这是一个新文件,全部内容如下:
server {
listen 81;
server_name web1;
root /usr/share/nginx/real1;
index index.html;
}
server {
listen 82;
server_name web2;
root /usr/share/nginx/real2;
index index.html;
}
server {
listen 83;
server_name web3;
root /usr/share/nginx/real3;
index index.html;
}
[root@bogon ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@bogon ~]# systemctl reload nginx.service
[root@bogon ~]# ss -anput | grep nginx
tcp LISTEN 0 511 0.0.0.0:81 0.0.0.0:* users:(("nginx",pid=6045,fd=16),("nginx",pid=6044,fd=16),("nginx",pid=5825,fd=16))
tcp LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=6045,fd=8),("nginx",pid=6044,fd=8),("nginx",pid=5825,fd=8))
tcp LISTEN 0 511 0.0.0.0:83 0.0.0.0:* users:(("nginx",pid=6045,fd=18),("nginx",pid=6044,fd=18),("nginx",pid=5825,fd=18))
tcp LISTEN 0 511 0.0.0.0:82 0.0.0.0:* users:(("nginx",pid=6045,fd=17),("nginx",pid=6044,fd=17),("nginx",pid=5825,fd=17))
tcp LISTEN 0 511 [::]:80 [::]:* users:(("nginx",pid=6045,fd=9),("nginx",pid=6044,fd=9),("nginx",pid=5825,fd=9))
[root@bogon ~]# mkdir /usr/share/nginx/real{1,2,3}
[root@bogon ~]# ls /usr/share/nginx/
html modules real1 real2 real3
// 定义81-83 端口的index文件
[root@bogon ~]# echo "81 port real webserver " > /usr/share/nginx/real1/index.html
[root@bogon ~]# echo "82222 port real webserver " > /usr/share/nginx/real2/index.html
[root@bogon ~]# echo "33333 port real webserver " > /usr/share/nginx/real3/index.html
[root@bogon ~]# cat /usr/share/nginx/real1/index.html
81 port real webserver
[root@bogon ~]# cat /usr/share/nginx/real2/index.html
82222 port real webserver
[root@bogon ~]# cat /usr/share/nginx/real3/index.html
33333 port real webserver
// 访问测试
[root@bogon ~]# curl http://127.0.0.1:81
81 port real webserver
[root@bogon ~]# curl http://127.0.0.1:82
82222 port real webserver
[root@bogon ~]# curl http://127.0.0.1:83
33333 port real webserver
// 定义后端工作池
[root@bogon ~]# vim /etc/nginx/conf.d/work_server.conf // 新文件
[root@bogon ~]# cat /etc/nginx/conf.d/work_server.conf
upstream realwebs {
server 127.0.0.1:81;
server 127.0.0.1:82;
server 127.0.0.1:83;
}
[root@bogon ~]# vim /etc/nginx/nginx.conf
[root@bogon ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@bogon ~]# systemctl reload nginx
// 注意这里使用默认的80端口访问,也就是通过80端口访问到了81 82 83 端口的响应内容
[root@bogon ~]# curl http://127.0.0.1
81 port real webserver
[root@bogon ~]# curl http://127.0.0.1
82222 port real webserver
[root@bogon ~]# curl http://127.0.0.1
33333 port real webserver
// 上面展示的负载均衡算法为轮询,在轮询时可以通过权重,让性能更好的节点多处理用户访问
[root@bogon ~]# cat /etc/nginx/conf.d/work_server.conf
upstream realwebs {
server 127.0.0.1:81 weight=3; // 设置81端口的权重为3,那么81-83 各个端口实际处理用户访问的比例大概为 3:1:1 未修改的情况下,默认所有节点的权重为1
server 127.0.0.1:82;
server 127.0.0.1:83;
}
[root@bogon ~]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@bogon ~]# systemctl reload nginx.service
[root@bogon ~]# curl http://127.0.0.1
81 port real webserver
[root@bogon ~]# curl http://127.0.0.1
82222 port real webserver
[root@bogon ~]# curl http://127.0.0.1
81 port real webserver
[root@bogon ~]# curl http://127.0.0.1
33333 port real webserver
[root@bogon ~]# curl http://127.0.0.1
81 port real webserver
[root@bogon ~]# curl http://127.0.0.1
81 port real webserver
[root@bogon ~]# curl http://127.0.0.1
82222 port real webserver
、
除此之外还可以设置nginx负载均衡的算法包括:
1、最少连接数 least_conn;
2、ip 哈希 ip_hash;
只需要将对应的算法名称单独写入upstream配置块中即可,例如:
[root@bogon ~]# cat /etc/nginx/conf.d/work_server.conf
upstream realwebs {
least_conn;
server 127.0.0.1:81 weight=3;
server 127.0.0.1:82;
server 127.0.0.1:83;
}
然而上图示例的架构中,在负载均衡也是就标记为前端节点的位置容易发生类似于
[root@bogon ansible]# cat ansible.cfg
[defaults]
inventory = ./hosts
host_key_checking = false
#修改默认值
[root@bogon ansible]# pwd
/root/ansible
[root@bogon ansible]# cat ansible.cfg
[defaults]
inventory = ./hosts
host_key_checking = false
[root@bogon ansible]# cat hosts
[realservers]
localhost
[proxyserver]
Localhost
#主机清单
[root@bogon ansible]# cat playbook.yml
- hosts: all
gather_facts: false
tasks:
- name: install nginx
dnf:
name: nginx
state: present
#下载nginx
- name: start service
service:
name: nginx
state: started
enabled: true
#开启服务
- name: real server config
copy:
src: files/real_web.conf
#指定了要复制的源文件的路径
dest: /etc/nginx/conf.d/real_web.conf
#目标路径
# only run on realservers group
#任务仅当远程主机属于realservers组时才会执行
when: '"realservers" in group_names'
#用于控制任务是否应该执行,条件表达式检查group_names(一个包含当前主机所属所有组的列表)中是否包含字符串"realservers"。如果包含,则条件为真,任务将执行;如果不包含,则条件为假,任务将被跳过。这确保了只有属于realservers组的主机才会执行这个复制操作。
- name: deploy a test page
debug:
#debug模块通常用于在Ansible执行过程中输出信息,帮助调试playbook。
msg: "this task should be replaced by a test file deploy task"
when: "'realservers' in group_names"
#条件表达式检查group_names中是否包含字符串'realservers'
- name: proxy server config about wokring pool
template:
#template模块用于将模板文件(包含变量和Jinja2模板语法的文件)渲染为实际文件,并将其复制到远程主机上。
src: files/work_server.conf
#模板文件位于Ansible控制机的files/work_server.conf目录下。
dest: /etc/nginx/conf.d/work_server.conf
#文件将被放置在/etc/nginx/conf.d/work_server.conf
# only run proxyserver group
when: '"proxyserver" in group_names'
- name: proxy server config proxy on default virtual server config
blockinfile:
#blockinfile模块用于在指定的文件中插入一个文本块,可以在文件的特定行之前或之后插入,或者如果文本块已存在则不进行任何更改。
block: |
location / {
proxy_pass http://realwebs;
}
#block参数后跟了一个多行字符串(由|指示),它是要插入文件的内容。在这个例子中,它是一个Nginx的location块,它将所有对根URL(/)的请求代理到http://realwebs。
insertbefore: '^ error_page 404 /404.html;$'
#insertbefore参数指定了插入位置。这意味着新的location块将被添加到这一行之前。
path: /etc/nginx/nginx.conf
#path参数指定了要修改的文件的路径,这里是/etc/nginx/nginx.conf,即Nginx的主配置文件。
# only run proxyserver group
when: '"proxyserver" in group_names'
#- include_tasks: proxy_tasks.yml
#- when: '"proxyserver" not in group_names'
#将尝试在条件为'"proxyserver" not in group_names'时包含并执行proxy_tasks.yml文件中的任务。
- name: restart service on all nodes
service:
name: nginx
state: reloaded
#重启Nginx服务
- name: test if all function works
hosts: localhost
gather_facts: false
#这告诉Ansible不要自动收集关于目标主机的信息(称为“facts”)。
tasks:
#这一行标志着任务列表的开始。
- name: use loop to test
uri:
#uri模块用于发送HTTP/HTTPS请求到指定的URL,并返回响应。
url: http://localhost
#它指向http://localhost,意味着将向本地机器上的HTTP服务发送请求。
return_content: true
#当设置为true时,它会将响应的内容作为任务的输出返回。
register: reponses
#注册到一个名为reponses的变量中
loop: [1, 2, 3]
- name: debug test result
debug:
#debug模块(在Ansible中)用于输出信息到控制台,通常用于调试目的。它可以显示变量的值或消息,帮助用户了解任务的执行状态和上下文。
#var: reponses
#debug模块输出名为reponses的变量的值。
msg: "{{ item.content }}"
#msg关键字用于指定debug模块将要显示的消息。
#item.content表示在循环的每次迭代中,都会尝试访问当前item(循环中的元素)的content属性或键的值。
loop: "{{ reponses.results }}"
[root@bogon ansible]# cat files/real_web.conf
server {
listen 81;
#监听81端口
server_name web1;
#定义了Nginx服务器块处理的请求应该匹配哪个域名
root /usr/share/nginx/real1;
#Nginx将从/usr/share/nginx/real1目录中查找资源。
index index.html;、
#Nginx应该尝试返回哪个文件作为响应。
}
server {
listen 82;
server_name web2;
root /usr/share/nginx/real2;
index index.html;
}
server {
listen 83;
server_name web3;
root /usr/share/nginx/real3;
index index.html;
}
[root@bogon ansible]# cat files/work_server.conf
upstream realwebs {
least_conn;
server 127.0.0.1:81 weight=3;
server 127.0.0.1:82;
server 127.0.0.1:83;
}
[root@bogon ansible]# ansible-playbook playbook.yml --ask-pass
因为设置了权重所以三次测试,代理节点并不会依次分发给81到82端口,81端口响应的次数更多,且每一次测试结果不一致