赞
踩
前言:本博客仅作记录学习使用,部分图片出自网络,如有侵犯您的权益,请联系删除
单个服务器的处理客户端(用户)请求能力有一个极限,当接入请求过多时,会造成服务器繁忙,可以使用多个服务器来共同分担成千上万的用户请求,这些服务器提供相同的服务,但对用户来说,感觉不到任何区别。
需要有一个负载均衡设备(即反向代理服务器)来分发用户请求,将用户请求分发到空闲的服务器上。服务器返回自己的服务到负载均衡设备。负载均衡设备将服务器返回用户。
正向代理:代理客户端,正向代理的过程隐藏了真实的请求客户端,服务器不知道真实的客户端是谁,客户端的服务都被代理服务器代替请求
反向代理:代理服务端,反向代理的过程隐藏了真实的服务器,客户端不知道真正提供服务的是谁,客户端请求的服务都被代理服务器接收
Apache/nignx是静态服务器(HTTP Server):
Apache优点:相对于Tomcat服务器来说处理静态文件是它的优势,速度快。Apache是静态解析, 适合静态HTML、图片等。
HTTP Server 关心的是 HTTP 协议层面的传输和访问控制,所以在 Apache/Nginx 上你可以看到代理、负载均衡等功能
HTTP Server(Nginx/Apache)常用做静态内容服务和代理服务器,将外来请求转发给后面的应用服务(tomcat,jboss,jetty等)。
应用服务器(tomcat/jboss/jetty)是动态服务器(Application Server):
应用服务器Application Server,则是一个应用执行的容器。它首先需要支持开发语言的 Runtime (对于 Tomcat 来说,就是 Java,若是Ruby/Python 等其他语言开发的应用也无法直接运行在Tomcat 上)。
应用服务器(如tomcat)往往也会集成 HTTP Server 的功能,nginx也可以通过模块开发来提供应用功能,只是不如专业的 HTTP Server 那么强大,所以应用服务器往往是运行在 HTTP Server 的背后,执行应用,将动态的内容转化为静态的内容之后,通过 HTTP Server分发到客户端
常用开源集群软件有:lvs,keepalived,haproxy,nginx,apache,heartbeat
常用商业集群硬件有:F5, Netscaler,Radware,A10等
- # ----------------代理--------------------#
- Syntax: proxy_pass URL; #代理的后端服务器URL
- Default: —
- Context: location, if in location, limit_except
-
- # ---------------缓冲区--------------------#
- Syntax: proxy_buffering on | off;
- Default: proxy_buffering on; #缓冲开关
- Context: http, server, location
- proxy_buffering # 开启的情况下,nignx会把后端返回的内容先放到缓冲区当中,然后再返回给客户端(边收边传,不是全部接收完再传给客户端)。
- Syntax: proxy_buffer_size size;
- Default: proxy_buffer_size 4k|8k; #缓冲区大小
- Context: http, server, location
- Syntax: proxy_buffers number size;
- Default: proxy_buffers 8 4k|8k; #缓冲区数量
- Context: http, server, location
- Syntax: proxy_busy_buffers_size size;
- Default: proxy_busy_buffers_size 8k|16k;#忙碌的缓冲区大小控制同时传递给客户端的
- buffer数量
- Context: http, server, location
-
- # ----------------头信息--------------------#
- Syntax: proxy_set_header field value;
- Default: proxy_set_header Host $proxy_host; #设置真实客户端地址
- proxy_set_header Connection close;
- Context: http, server, location
-
- # ----------------超时--------------------#
- Syntax: proxy_connect_timeout time;
- Default: proxy_connect_timeout 60s; #链接超时
- Context: http, server, location
-
- Syntax: proxy_read_timeout time;
- Default: proxy_read_timeout 60s;
- Context: http, server, location
-
- Syntax: proxy_send_timeout time; #nginx进程向fastcgi进程发送request的整个过程的超时时间
- Default: proxy_send_timeout 60s;
- Context: http, server, location
在proxy_buffering开启的情况下,Nginx会尝试将上游服务器的所有数据读入缓冲区,直到所有proxy_buffers被填满或数据结束。
数据开始向客户端传输,同时Nginx继续接收数据并可能将其写入临时文件,由proxy_max_temp_file_size控制大小。
如果响应内容很大,Nginx会从临时文件继续读取数据,直到传输完成。
忙碌缓冲区:一旦proxy_buffers中的缓冲区被填满,它们就会处于忙碌状态,直到其中的数据完全传输给客户端。忙碌缓冲区的总大小不能超过proxy_busy_buffers_size,这个参数用来控制同时向客户端传输的缓冲区数量。
角色 | |
---|---|
nginx-1:10.0.0.2 | 网站服务器 |
nginx-2:10.0.0.3 | 代理服务器 |
- [root@centos ~]# cat /usr/share/nginx/html/index.html
- This is proxy test!
- [root@centos ~]# nginx -t
- nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
- nginx: configuration file /etc/nginx/nginx.conf test is successful
- [root@centos ~]# nginx -s reload
- [root@centos ~]# cat /etc/nginx/conf.d/default.conf
- server {
- listen 80;
- server_name localhost;
- location / {
- proxy_pass http://10.0.0.2:80; # 真实服务器地址:IP/域名
- proxy_redirect default; # 代理后的URL重定向行为,默认情况下不进行重定向
- proxy_set_header Host $http_host; # 转发请求时使用原始请求中的Host头
- proxy_set_header X-Real-IP $remote_addr; # X-Real-IP头:客户端IP地址
- #proxy_set_header REMOTE-HOST $remote_addr; # REMOTE-HOST:客户端IP地址
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 跟踪请求经过的代理服务器
- proxy_connect_timeout 30; # 与后端服务器建立连接的超时时间
- proxy_send_timeout 60; # 向后端服务器发送请求的超时时间
- proxy_read_timeout 60; # 从后端服务器读取响应的超时时间
- proxy_buffering on; # 开启响应缓冲,可以提高代理性能
- proxy_buffer_size 32k; # 缓冲区的大小
- proxy_buffers 4 128k; # 缓冲区的数量和大小
- proxy_busy_buffers_size 256k; # 忙碌缓冲区的大小
- proxy_max_temp_file_size 256k; # 临时文件的最大大小
- }
- }
- [root@centos ~]# nginx -t
- nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
- nginx: configuration file /etc/nginx/nginx.conf test is successful
- [root@centos ~]# nginx -s reload
成功访问nginx-1服务器页面
若想使用域名进行访问,在 C:\Windows\System32\drivers\etc\hosts 文件中添加一行 | (linux:/etc/hosts)
- # 主机IP 配置的域名
- 10.0.0.3 www.test.com
- [root@centos ~]# cat /var/log/nginx/access.log
- 10.0.0.3 - - [09/Aug/2024:18:41:08 +0800] "GET /favicon.ico HTTP/1.0" 404 555 "http://10.0.0.3/" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36" "10.0.0.1"
-
- # 10.0.0.3:代理服务器地址
- # 10.0.0.1:客户机地址
访问成功。记录了客户机的IP和代理服务器的IP
在计算机的世界里,负载均衡就是让多个服务器或者网络资源来分担工作,这样即使某个服务器或者资源很忙或者出现问题,其他的服务器或资源还可以继续工作,保证整个系统的稳定和效率。
下面的配置是解决方案之一
proxy_connect_timeout 1; #nginx服务器与被代理的服务器建立连接的超时时间,默认60秒 proxy_read_timeout 1; #nginx服务器想被代理服务器组发出read请求后,等待响应的超时间,默认为60秒
proxy_send_timeout 1; #nginx服务器想被代理服务器组发出write请求后,等待响应的超时间,默认为60秒
proxy_ignore_client_abort on; #客户端断网时,nginx服务器是否中断对被代理服务器的请求。默认为off
使用upstream指令配置一组服务器作为被代理服务器,服务器中的访问算法遵循配置的负载均衡规则,同时可以使用该指令配置在发生哪些异常情况时,将请求顺次交由下一组服务器处理
proxy_next_upstream timeout; #反向代理upstream中设置的服务器组,出现故障时,被代理服务器返回的状态值。 error|timeout|invalid_header|http_500|http_502|http_503|http_504|http_404|off
实现Nginx负载均衡的组件主要有两个:
ngx_http_proxy_module:proxy代理模块;用于把请求转发给服务器节点或upstream服务器池
upstream模块允许Nginx定义一组或多组节点服务器组,使用时可以通过proxy_pass代理方式把网站的请求发送到事先定义好的对应upstream组的名字上,具体写法为:
proxy_pass http://server_pools
server_pools就是一个upstream节点服务器组名字
- upstream server_pool {
- server 10.0.0.2; # 默认80端口
- server 10.0.0.3;
- }
参数 | 说明 |
---|---|
server | 负载后面的RS配置,可以是ip或者域名 |
weight | 请求服务器的权重。默认值为1,越大表示接受的请求比例越大 |
max_fails | nginx 尝试连接后端主机失败的次数,需要配合proxy_net_upstream ,fastcgi_next_upstream 和memcached_next_upstream 这三个参数来使用 |
fail_timeout | 在max_fails 定义的失败次数后,距离下次检查的时间间隔,默认10s |
backup | 热备配置,标志这台服务器作为备份服务器,若主服务器全部宕机了,就会向它转发请求 |
down | 表示这个服务器永不可用,可配合ip_hash使用 |
下面给出一个示例:
- upstream web_pools {
-
- server linux.example.com weight=5;
- server 127.0.0.1:8080 max_fail=5 fail_timeout=10s;
- # 当5次连续检查失败后,间隔10s后重新检测。
- server linux.example.com:8080 backup;
- # 指定备份服务器。作用:等上面服务器全部不可访问时就向它转发请求。
-
- }
proxy_pass指令属于ngx_http_proxy_module模块,此模块可以将请求转发到另一台服务器上。在实际的反向代理工作中,会通过location功能匹配指定的URI,然后把接收到的符合匹配URI的请求通过proxy_pass抛给定义好的upstream节点池
参数 | 说明 |
---|---|
proxy_set_header | 设置http请求header项传给后端服务器节点 |
client_body_buffer_size | 指定客户端请求主题缓冲区大小 |
proxy_connect_timeout | 表反向代理与后端节点服务器连接的超时时间,即发起握手等候响应的超时时间 |
proxy_send_timeout | 表示代理后端服务器的数据回传时间,即在规定时间之内,后端服务器必须传完所有的数据,否则,nginx将断开这个连接 |
proxy_read_timeout | 设置nginx从代理的后端服务器获取信息的时间,表示连接建立成功后,nginx等待后端服务器的响应时间,其实是nginx在后端排队等候处理的时间 |
proxy_buffer_size | 设置缓冲区大小,默认该缓冲区大小等于指令proxy_buffers设置的大小 |
proxy_buffers | 设置缓冲区的数量和大小,nginx从代理的后端服务器获取的响应信息,会放置在缓冲区 |
proxy_busy_buffers_size | 用于设置系统很忙时可以使用的proxy_buffers大小,官方推荐的大小为proxy_bufer*2 |
proxy_temp_file_write_size | 指定proxy缓存临时文件的大小 |
upstream支持4种负载均衡调度算法:
默认调度算法,每个请求按时间顺序逐一分配到不同的后端服务器,宕机的服务器会自动从节点服务器池中剔除。
- upstream server_pool {
- server 10.0.0.2;
- server 10.0.0.2;
- }
注意:对于服务器性能不同的集群,该算法容易引发资源分配不合理等问题
在rr轮询算法的基础上加上权重,权重和用户访问成正比,权重值越大,被转发的请求也就越多
- upstream server_pool {
- server 10.0.0.2 weight=5;
- server 10.0.0.2 weight=10;
- }
加权轮询应用于服务器性能不等的集群中,使资源分配更加合理化
每个请求按访问IP的hash结果分配,同一个IP客户端固定访问一个后端服务器。可以保证来自同一ip的请求被打到固定的机器上,可以解决session问题
- upstream server_pool {
- ip_hash;
- server 10.0.0.2;
- server 10.0.0.2;
- }
此种算法根据后端服务器的响应时间来分配请求,响应时间短的优先分配。 Nginx 本身是 不支持 fair 的,如果需要使用这种调度算法,必须下载Nginx的 upstream_fair 模块
- upstream server_pool {
- server 10.0.0.2;
- server 10.0.0.2;
- fair;
- }
根据访问URL的hash结果来分配请求,让每个URL定向到同一个后端服务器, 同样,Nginx本身是不支持url_hash,如果需要使用这种调度算法,必须安装Nginx的hash模块软件包。
- upstream server_pool {
- server 10.0.0.2; # 指定后端服务器的地址和端口
- server 10.0.0.2;
- hash $request_uri; # 使用哈希方法来分配请求并使用请求的URI作为哈希的键
- hash_method crc32; # 使用CRC32算法来计算哈希值
- }
在浏览器输入http://testapp.com,实现负载均衡效果(平均访问到两台服务器)
这边使用两台服务器以及一台负载均衡器
主机名 | IP地址 | 角色 |
---|---|---|
centos-1 | 10.0.0.2 | nginx服务器 |
centos-2 | 10.0.0.3 | nginx服务器 |
centos-3 | 10.0.0.4 | nginx 负载均衡服务器 |
为了更便于观察到负载均衡实现出的效果,下面为两台服务器编写不同的首页文件
- # 配置文件参数默认即可,下面修改首页测试文件
- [root@centos-1 ~]# cat /usr/share/nginx/html/index.html
- My domain IP is 10.0.0.2
-
- [root@centos-2 ~]# cat /usr/share/nginx/html/index.html
- My domain IP is 10.0.0.3
- [root@centos ~]# nginx -s reload
- # nginx服务别忘记启动
- [root@centos-3 ~]# cat /etc/nginx/conf.d/default.conf
- upstream testapp {
- server 10.0.0.2:80;
- server 10.0.0.3:80;
- }
- server {
- listen 80;
- server_name localhost;
- location / {
- proxy_pass http://testapp;
- }
- }
因为使用域名进行访问,在 C:\Windows\System32\drivers\etc\hosts 文件中添加一行 | (linux:/etc/hosts)
- # 主机IP 配置的域名
- 10.0.0.4 www.testapp.com
不断刷新会发现所有请求被负载均衡器(10.0.0.4)均分配到10.0.0.2和10.0.0.3服务器上,实现了负载均衡的效果
OSI(Open System Interconnection)是一个开放性的通行系统互连参考模型,他是一个定义的非常好的协议规范,共包含七层协议
TCP/IP协议
之所以说TCP/IP是一个协议族,是因为TCP/IP协议包括TCP、IP、UDP、ICMP、RIP、TELNETFTP、SMTP、ARP、TFTP等许多协议,这些协议一起称为TCP/IP协议。
从协议分层模型方面来讲,TCP/IP由四个层次组成:网络接口层、网络层、传输层、应用层:
在nginx做负载均衡,负载多个服务,部分服务是需要7层的,部分服务是需要4层的,也就是说7层和4层配置在同一个配置文件中
在这同样使用第三点负载均衡中的机器环境
使用负载均衡来分发请求到多个上游服务器,编辑/etc/nginx/nginx.conf:
- worker_processes 4;
- worker_rlimit_nofile 102400;
- events {
- worker_connections 1024;
- }
- http {
- include mime.types;
- default_type application/octet-stream;
- 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 logs/access.log main;
- sendfile on;
- keepalive_timeout 65;
- gzip on;
- # 定义两个上游服务器组,testweb和testapp,用于负载均衡
- upstream testweb {
- ip_hash;
- server 10.0.0.2:80 weight=2 max_fails=2 fail_timeout=2s;
- server 10.0.0.3:80 weight=2 max_fails=2 fail_timeout=2s;
- }
- server {
- listen 80;
- server_name www.test.com;
- charset utf-8;
- #access_log logs/host.access.log main;
- location / {
- proxy_pass http://testweb;
- proxy_set_header Host $host:$server_port;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
- error_page 500 502 503 504 /50x.html;
- location = /50x.html {
- root html;
- }
- }
-
- upstream testapp {
- server 10.0.0.2:8081 weight=2 max_fails=2 fail_timeout=2s;
- server 10.0.0.3:8081 weight=2 max_fails=2 fail_timeout=2s;
- }
- server {
- listen 81;
- server_name www.app.com;
- charset utf-8;
- #access_log logs/host.access.log main;
- location / {
- proxy_pass http://testapp;
- proxy_set_header Host $host:$server_port;
- proxy_set_header X-Real-IP $remote_addr;
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
- }
- }
- }
在使用yum安装的nginx版本大于1.9.0的时候,增加了一个stream模块,来实现4层协议(网络层和传输层)的转发、代理、负载均衡等。stream模块的用法跟http的用法类似,允许我们配置一组TCP或者UDP等协议的监听,然后通过proxy_pass来转发我们的请求,通过upstream添加多个后端服务,实现负载均衡。
- stream {
- upstream myweb {
- hash $remote_addr consistent;
- server 172.17.14.2:8080;
- server 172.17.14.3:8080;
- }
- server {
- listen 82;
- proxy_connect_timeout 10s;
- proxy_timeout 30s;
- proxy_pass myweb;
- }
- }
这个上述介绍过;ip_hash使用源地址哈希算法,将同一客户端的请求总是发往同一个后端服务器,除非该服务器不可用
- upstream backend {
- ip_hash;
- server backend1.example.com;
- server backend2.example.com;
- server backend3.example.com down;
- }
ip_hash简单易用,但有如下问题:
使用sticky_cookie_insert启用会话亲缘关系,这会导致来自同一客户端的请求被传递到一组服务器的同一台服务器。与ip_hash不同之处在于,它不是基于IP来判断客户端的,而是基于cookie来判断。因此可以避免上述ip_hash中来自同一局域网的客户端和前段代理导致负载失衡的情况。(需要引入第三方模块才能实现)
- upstream backend {
- server backend1.example.com;
- server backend2.example.com;
- sticky_cookie_insert srv_id expires=1h domain=3evip.cn path=/;
- }
- # expires:设置浏览器中保持cookie的时间
- # domain:定义cookie的域
- # path:为cookie定义路径
jvm_route是通过session_cookie这种方式来实现session粘性。将特定会话附属到特定tomca上,从而解决session不同步问题,但是无法解决宕机后会话转移问题。如果在cookie和url中并没有session,则这只是个简单的round-robin负载均衡。
jvm_route的原理:
暂时jvm_route模块还不支持fair的模式。jvm_route的工作模式和fair是冲突的。对于某个特定用户,当一直为他服务的Tomcat宕机后,默认情况下它会重试max_fails的次数,如果还是失败,就重新启用round robin的方式,而这种情况下就会导致用户的session丢失
使用数据库、redis、memcached等做session复制
在此,我要对所有为知识共享做出贡献的个人和机构表示最深切的感谢。同时也感谢每一位花时间阅读这篇文章的读者,如果文章中有任何错误,欢迎留言指正。
学习永无止境,让我们共同进步!!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。