本质:反向代理+负载均衡
7层负载均衡可用来重定向(例如客户端访问www.taobao.com重定向到https://www.taobao.com/,从80端口跳转到443)
一、反向代理和正向代理的区别
1.代理服务器如果配置在客户端即为正向代理,如果配置在服务端即为反向代理,和机器个数没有关系
2.正向代理代替客户端去发送请求,反向代理代替服务端接受请求
3.正是因为正向代理代替客户端发送请求,正向代理服务器和客户端对外表现为一个客户端,所以正向代理隐藏了真实的客户端;
反向代理代替服务端接受请求,反向代理服务器和真实服务器对外表现为一个服务端,所以反向代理服务器隐藏真实的服务端
综上,本质上代理服务器还是那个代理服务器,如果替客户端干活就是正向代理,如果替服务端干活就是反向代理;
如下图所示
服务器不仅可以作为服务端,也可以作为客户端;如果该服务器向某些客户端提供资源,此时就是服务端,同时如果需要向别的服务器请求资源,此时就是客户端。
二、实验操作
1、nginx安装
本文实验使用nginx源码安装(也可以下载编译好的):下载相应版本源码包,lftp传输到server1上解压;configure相当于GNU组织的make
源码编译三步曲:
第一步:configure校验操作系统的依赖性
./configure --help获取参数
./configure --with-http_ssl_module --with-http_stub_status_module --prefix=/usr/local/nginx
--with选定模块(默认没有) --without选定不要的模块(默认是有的) --prefix指定安装路径(第三方软件一般在/usr/local/下)
--with-http_ssl_module常规http模块 --with-http_stub_status_module监控模块
提示c语言编辑器没安装,安装gcc解决依赖性
安装完后,在执行./configure,--prefix指定安装路径
提示没有PCRE模块,安装模块pcre-devel开发包;红帽开发包都是以-devel后缀命名的;
继续configure,没有openssl,安装openssl包
再次configure检测通过
第二步:执行make编译,把c语言编译为2进制
第三步:make install安装;上面make和make install命令要在Makefile文件的目录下执行
安装完成后,nginx所有程序要运行在安装路径/usr/local/nginx下,源码目录nginx-1.20.2可以删掉了。(类似windows,安装完后删除软件安装压缩包和解压的压缩包)
二进制文件nginx在/usr/local/nginx/sbin/nginx,不在系统环境变量里面,打开nginx命令要绝对路径/usr/local/nginx/sbin/nginx或者在此目录下使用nginx
为了方便做一个软连接ln -s /usr/local/nginx/sbin/nginx /usr/local/bin/ 把二进制文件nginx链接到系统环境变量里,这样可以在任意位置执行nginx命令。
以下代码依次:ls;软连接;查看nginx命令位置;ll查看nginx二进制文件信息;检测语法;打开nginx;ps查看进程;
访问localhost到nginx界面
关闭nginx
不能多次启动,因为一次启动0.0.0.0:80端口已经被占用,再启动会报错,显示0.0.0.0:80端口已经被占用,如果其他服务已经占用80端口也会报错)
默认此端口0.0.0.0:80监听本机所有端口,可以从远程访问
默认访问的nginx文件为/usr/local/nginx/html/index.html
2、nginx更改配置文件
server1作为调度器,server2、3作为real server
server1上配置文件位置/usr/local/nginx/conf/mginx.conf
1、在http{}内(http{...server{}......}内参数针对所有虚拟主机server{},server{}内参数只是针对本虚拟主机生效),upstream添加名称为westos的负载均衡器(因为niginx7层,可以支持端口映射,端口号可为8080或其他),默认算法是rr论调,两个real server地址
2、localhost的server{}不动,重新创建server{}
监听80端口:172.25.254.1:80;servername 域名www.westos.org;通过location 根,通过proxy_pass访问上一步定义的westos负载均衡器(http://westos)
过程:当访问域名www.westos.org时,域名解析到172.25.254.1上,nginx来处理,由location的proxy_pass处理,所有请求转发到负载均衡器westos,调度到后端real server上,后端real server80端口是httpd服务的index.html文件(172.25.254.2:80的index.html上显示server2;172.25.254.3:80的index.html上显示server3),实现负载均衡。本质反向代理+负载均衡
nginx检测;改完配置文件nginx reload
客户端38上访问域名www.westos.org需要解析到调度器172.25.254.1上去,(在那个客户端上访问域名,那个客户端要做解析到调度器172.25.254.1上)
客户端38上访问域名curl www.westos.org,正常论调
server2上停掉httpd:systemctl stop httpd
有健康检测,nginx调度列表删掉server2,只调度到server3上
当server3上停掉httpd:systemctl stop httpd
报错502表示没有可用后端
3 nginx配置文件优化
3.1添加server1为备用real server,更改server2权重
server1上更改配置文件vim conf/nginx.conf(/usr/local/nginx目录下):
添加本机(server1)为备用后端,当server2、3httpd都停掉后(systemctl stop httpd),server1调度器调度到server1上;更改server2的权重weight=2。下面localhost指server1
调度到server1上访问的是nginx的发布目录,默认写在nginx配置文件中,下图所示(server2、3使用httpd占用80端口,访问的是httpd的发布目录index.html;server1 nginx占用80端口,访问nginx的发布目录)
server2、3都停掉,调度到server1
server2、3httpd服务打开后,server1不再调度,实现论调,但server2权重为2,调度次数多。
3.2 使用ip_hash:一个客户端调度到一个后端,(相同ip地址的请求,发往相同的后台服务器)符合生产环境。生产环境要求整体负载均衡,不需要来回论调。
有的服务器之间没有作共享,客户端调度到一个服务器进行操作后,如果又调度到另一个服务器上之前操作得重来。
更改server1上nginx配置文件:ip_hash模式不能有backup备用后端;
客户端38上访问调度到server2上。
停掉server2的httpd服务,调度到server3上;重新打开server2,又调度回server2。
3.3手动下线
维护后端服务器时,防止误报,下线server2。
3.4使用sticky cookie
nginx 负载均衡流程:client 出现请求-> 通过dns解析 ->CDN(可使用nginx二次开发)(cache)(分布式集群作缓存,1加速客户端访问2降低real server负载) -> real server ->返回CDN作缓存 -> client
上述real server拿到的是CDN(此处是nginx代理服务器server1)的ip,客户端访问代理服务器(nginx server1),代理服务器去后端取,取完以后返回给客户端。后端不知道客户端的ip信息。
客户端curl www.westos.org,后端real server拿不到客户端ip地址,上面ip_hash就是如此。
解决:使用sticky cookie,但此方法要更新并重新编译nginx
设置nginx对外隐藏版本,防止被攻击,删掉“nginx/”后面版本信息
下载解压sticky
./configure;make(更新nginx,不要make install),编译前关掉nginx(nginx静态编译,更新功能时,每次要重新编译,且加载之前所有参数。)
更新完得到新的二进制可执行文件nginx,复制到安装目录,替代原有nginx
nginx -t检测语法,-s reload重新加载配置文件
更改nginx配置文件,基于cookie的反向代理sticky
cookie 存在浏览器中,要用浏览器进行访问,不停刷新始终是server3,因为客户端的信息存在网页cookie中,后端知道访问的客户端信息,实现一个后端处理一个客户端。
但客户端38上面没有cookie信息,后端不知道客户端信息,只能论调
3.5 ip_hash和sticky都能解决一个后端处理一个客户端的访问,但是ip_hash后端不知道客户端的信息,而sticky通过将客户端信息存在网页cookie中,知道客户端信息。
附件:nginx配置文件:nginx.conf
user nginx;
worker_processes 2;
worker_cpu_affinity 01 10;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 65535;
}
http {
upstream westos {
#ip_hash;
sticky;
server 172.25.254.2:80;
server 172.25.254.3:80;
}
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;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm;
# }
#}
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
server {
listen 80;
server_name www.westos.org;
location / {
proxy_pass http://westos;
}
}
}