docker安装nginx实现负载均衡
1docker安装nginx
此过程中将配置信息挂载到了宿主机内,所以可以在宿主机进行修改配置文件
第一步:拉取ngnix镜像 (从这里hub.docker.com去查找)
docker pull nginx
复制代码
第二步:查看images镜像
docker images
复制代码
第三步:简单启动(这个目的是为了拿到nginx的默认资源文件,默认会释放到/etc/nginx目录)
docker run --name nginx -d nginx
复制代码
检测安装的内容,可以查看nginx下/etc/nginx文件夹下的内容,执行不执行都可以
docker exec nginx ls -l /etc/nginx
复制代码
第四步:拷贝安装好的配置文件(将nginx容器服务中的文件拷贝宿主机指定目录)
docker cp -a nginx:/etc/nginx /usr/local/docker/nginx
复制代码
强制卸载刚刚安装的nginx,不用执行
docker rm -f nginx
复制代码
第六步:启动nginx容器,运行nginx镜像
sudo docker run -p 80:80 --restart always --name nginx \
-v /usr/local/docker/nginx/:/etc/nginx/ \
-v /usr/local/docker/nginx/conf.d:/etc/nginx/conf.d \
-d nginx
复制代码
第七步:进行访问检测,如图所示:
2nginx入门
docker下ngidnx容器的创建和启动(假如已有则无需再创建启动)
sudo docker run -p 80:80 --restart always --name nginx \
-v /usr/local/docker/nginx/:/etc/nginx/ \
-v /usr/local/docker/nginx/conf.d:/etc/nginx/conf.d \
-d nginx
复制代码
说明:nginx的启动必须在根目录中执行.
开启nginx
docker start nginx
复制代码
重启nginx
docker restart nginx
复制代码
停止nginx
docker stop nginx
复制代码
进入nginx容器
docker exec -it nginx bash
复制代码
查看nginx版本(docker中需要在容器内部执行)
nginx -v
复制代码
重新加载配置文件(docker中需要在容器内部执行)
service nginx reload
复制代码
3核心配置文件
Nginx的核心配置为conf目录下的nginx.conf,其初始默认配置如下:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/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 /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf; #嵌套
}
复制代码
其中,nginx的配置有三部分构成,在docker环境中nginx采用了嵌套加载方式,即主配置在/etc/nginx/nginx.conf中,然而平时用到的server配置在/etc/nginx/conf.d中,在主配置中见include指令部分,在conf.d目录下默认会有一个default.conf文件,这部分配置文件就是基本的server配置。无论采用怎样的配置方式,nginx.conf都只有这三部分构成,例如:
§ 全局块:配置文件开始到events中间的部分内容,主要是结合硬件资源进行配置
§ events块:这块主要是网络配置相关内容,硬件性能好,连接数可以配置更多
§ http块:nginx配置中最核心部分,可以配置请求转发,负载均衡等。
3入门案例
第一步:准备SpringBoot的web服务,并打成jar包(例如tomcat8901.jar)
将此springboot项目以8901,8902,8903打成3个jar包,放到宿主机的目录中
@RestController
public class HelloController {
@Value("${server.port}")
private String port;
//要求动态获取真实服务器端口号
@RequestMapping("/hello")
public String doSayHello() {
return "server:"+port+" say hello ";
}
}
复制代码
将项目放进宿主机的/usr/local/tomcatweb目录下,目录可以随意指定,只要找得到
后台启动SpringBoot项目,按照这种方式将三个SpringBoot项目启动
nohup java -jar tomcatweb8901.jar > catalina8901.out 2>&1 &
复制代码
查看启动运行日志
cat catalina8901.out
复制代码
nohup命令详解
nohup:不挂断地运行命令,退出帐户之后继续运行相应的进程。
>日志文件名.log:是nohup把command的输出重定向到当前目录的指定的“日志文件名.log”文件中,即输出内容不打印到屏幕上,而是输出到”日志文件名.log”文件中。不指定文件名会在当前目录创建nohup.out,如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。如果没有文件能创建或打开以用于追加,那么 Command 参数指定的命令不可调用。
2>&1:2就是标准错误,1是标准输出,该命令相当于把标准错误重定向到标准输出么。这里&相当于标准错误等效于标准输出,即把标准错误和标准输出同时输出到指定的“日志文件名.log”文件中。
java -jar 自己的springboot项目.jar:执行springboot的项目,如果单单只执行该命令,linux只会短暂的运行该项目,当退出控制台后会自动关闭该项目。
最后的&:让该作业在后台运行。
nohup java -jar waimaiurl-0.0.1-SNAPSHOT.jar >/home/ubuntu/clf/test.log>&1 &
复制代码
nohup java -jar 项目名称.jar >/路径名称/输出的日志名称.log>&1&
杀死后台进程
使用jobs -l 可以查看nohup后台运行的进程
jobs -l
复制代码
使用kill -9 pid号进行杀死进程
kill -9 pid
复制代码
配置请求转发
配置nginx实现请求的转换,在docker环境下可编辑
/usr/local/default/nginx/conf.d/目录中的default.conf文件,详细配置请求转发见红色代码如下:
server {
listen 80;
listen [::]:80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
proxy_pass http://192.168.174.130:8901;
#root /usr/share/nginx/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 /usr/share/nginx/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;
#}
}
复制代码
第三步:配置完以后重新启动nginx。
docker restart nginx
复制代码
第四步:对资源进行访问检测请求转发实现。
http://ip:80/hello
复制代码
访问后发现每次都是不同的端口号执行的
4nginx实战分析
需要搭建tomcat服务器集群,共同抗击高并发.这时需要使用反向代理服务器.同时配置负载均衡.
说明:准备3台tomcat服务器.端口号分别为8901/8902/8903.
启动方式在“3入门案例”中有详细讲解
(1)负载均衡策略
说明:根据配置文件的顺序,依次访问服务器.
可在docker环境下可编辑
/usr/local/default/nginx/conf.d/目录中的default.conf文件
#配置windows集群 默认是轮询策略
upstream gateways{
server 192.168.227.131:8901;
server 192.168.227.131:8902;
server 192.168.227.131:8903;
}
#配置后台管理服务器
server {
listen 80;
server_name localhost;
location / {
#实现http请求的转发
proxy_pass http://gateways;
}
}
复制代码
修改完毕后重启nginx
docker restart nginx
复制代码
然后根据ip地址和请求路径进行请求
http://ip:80/hello
复制代码
(2)权重策略
说明:可以为某些服务器添加权重,让该服务器更多的为用户提供服务
#配置windows集群 默认是轮循策略 权重
upstream gateways{
server 192.168.227.131:8901 weight=6;
server 192.168.227.131:8902 weight=3;
server 192.168.227.131:8903 weight=1;
}
复制代码
修改完毕后重启nginx
docker restart nginx
复制代码
然后根据ip地址和请求路径进行请求
http://ip:80/hello
复制代码
(3)IPHASH策略
问题说明:如果采用集群的部署,如果做敏感操作时,要求用户必须登录.但是由于nginx实现了负载均衡的操作,导致用户的Session数据不同共享.从而导致用户频繁登录.用户体验较差.
问题: nginx实现了tomcat负载均衡. 导致用户每次访问都是不同的服务器.
解决方案: 能否让用户每次访问同一台服务器 IPHASH策略
IPHASH调用原理 如图所示:
配置如下:
#配置windows集群 默认是轮询策略 权重
upstream geteways {
ip_hash;
server 192.168.227.131:8901 weight=6;
server 192.168.227.131:8902 weight=3;
server 192.168.227.131:8903 weight=1;
}
复制代码
IPHASH****存在的问题
-
IPHASH如果一旦服务器出现异常,导致业务失效.
-
可能会出现负载不均的现象.负载有高有低(可在测试中试用).
一般不会使用IPHASH,一般在测试中使用.
修改完毕后重启nginx
docker restart nginx
复制代码
然后根据ip地址和请求路径进行请求
http://ip:80/hello
复制代码
5NGINX常用属性
(1)Down属性
说明:如果服务器宕机,可以在配置文件中标识为down.这样以后不会再访问故障机.
upstream geteways {
#ip_hash;
server 192.168.227.131:8901 down;
server 192.168.227.131:8902;
server 192.168.227.131:8903;
}
复制代码
(2)BACKUP 设计
说明:备用机设置,正常情况下该服务器不会被访问.当主机全部宕机或者主机遇忙时,该服务器才会访问.
upstream geteways {
#ip_hash;
server 192.168.227.131:8901 down;
server 192.168.227.131:8902:8082;
server 192.168.227.131:8903 backup;
}
复制代码
(3)宕机服务器高可用实现
说明:当服务器宕机时,如果访问的失败达到最大失败次数,则标识为down.自动完成.在一定的周期之内,如果服务器恢复正常,则还会尝试访问故障机.
max_fails=1 最大的失败次数
fail_timeout=60s; 设定周期为60秒
upstream geteways {
#ip_hash;
server 192.168.227.131:8901 max_fails=1 fail_timeout=60s;
server 192.168.227.131:8902 max_fails=1 fail_timeout=60s;
server 192.168.227.131:8903 max_fails=1 fail_timeout=60s;
}
复制代码
6Nginx面试问题分析
(1)为什么不采用多线程模型管理连接?**
-
采用独立的进程,可以让互相之间不会影响。一个进程异常崩溃,其他进程的服务不会中断,提升了架构的可靠性。
-
进程之间不共享资源,不需要加锁,所以省掉了锁带来的开销。
(2)为什么不采用多线程处理逻辑业务?
-
进程数已经等于核心数,再新建线程处理任务,只会抢占现有进程,增加切换代价。
-
作为接入层,基本上都是数据转发业务,网络 IO 任务的等待耗时部分,已经被处理为非阻塞/全异步/事件驱动模式,在没有更多 CPU 的情况下,再利用多线程处理,意义不大。并且如果进程中有阻塞的处理逻辑,应该由各个业务进行解决,比如 openResty 中利用了 Lua 协程,对阻塞业务进行了优化。