docker安装nginx实现负载均衡

916 阅读6分钟

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

第七步:进行访问检测,如图所示: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UJDesCUK-1623757599850)(C:\Users\沉思\AppData\Roaming\Typora\typora-user-images\1623755487204.png)]

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;
    #}
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3eOz6QGq-1623757599853)(C:\Users\沉思\AppData\Roaming\Typora\typora-user-images\1623756482868.png)]

第三步:配置完以后重新启动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调用原理 如图所示: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eV7DzoYn-1623757599855)(C:\Users\沉思\AppData\Roaming\Typora\typora-user-images\1623756776424.png)]

配置如下:

#配置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****存在的问题

  1. IPHASH如果一旦服务器出现异常,导致业务失效.

  2. 可能会出现负载不均的现象.负载有高有低(可在测试中试用).

一般不会使用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)为什么不采用多线程模型管理连接?**

  1. 采用独立的进程,可以让互相之间不会影响。一个进程异常崩溃,其他进程的服务不会中断,提升了架构的可靠性。

  2. 进程之间不共享资源,不需要加锁,所以省掉了锁带来的开销。

(2)为什么不采用多线程处理逻辑业务?

  1. 进程数已经等于核心数,再新建线程处理任务,只会抢占现有进程,增加切换代价。

  2. 作为接入层,基本上都是数据转发业务,网络 IO 任务的等待耗时部分,已经被处理为非阻塞/全异步/事件驱动模式,在没有更多 CPU 的情况下,再利用多线程处理,意义不大。并且如果进程中有阻塞的处理逻辑,应该由各个业务进行解决,比如 openResty 中利用了 Lua 协程,对阻塞业务进行了优化。