• 使用nginx+docker实现一个简单的负载均衡


    目录

    前言

     提出需求

    开始

    启动nginx

    启动一个Django容器

    部署多台服务器

    1.打包一个容器

     2.开启多台服务

    3.在各个容器中启动django项目

     配置nginx文件实现反向代理和负载均衡

    检验

    配置负载均衡的其他方法

    1.轮询(默认)

    2.加权轮询算法

    3.ip_hash算法

    4.最少连接数算法

    5.url_hash算法

    6.fair算法


    前言

    对于一个服务,当并发请求量较大时,一个服务器可能就会处理不过来,这时候就需要加多台服务器,来处理这些并发的请求,而在这么多的服务器中,当前的请求具体大道哪台服务器上呢?这个时候我们就可以用到nginx提供的的负载均衡功能,我们可以根据每台服务器的配置,将配置好一点的服务器设置更高的权重;配置低一点的服务器就设置低一点的权重,这时候较多的请求就会打在配置好一点的服务器上,较少的请求就会打在配置差一点的服务器上,从而就实现了负载均衡。

    因此要想实现一个负载均衡,前提条件是我们得有多台服务器,因为资源有限,我这里就以docker启动的每台容器当做一台服务器。同时我也会将nginx运行在一个单独的容器中,也将其假设成一个单独的服务器。这时候也相当于实现了反向代理的功能。

     提出需求

    我们还是以需求驱动,有了需求之后,我们才好根据需求做出对应的决策,才好对症下药!假设我们有这样一个需求:访问我们服务的地址后,返回此时访问的真正的服务器的名称。

    大体架构如下:

     

    我们假设总共有7台服务器,一台用作反向代理用,另外六台是真正提供服务的服务器。

    开始

    启动nginx

    启动一个nginx,将容器端口80映射到本地的7777

    docker run -it -p 7777:80  --name mynginx  nginx  /bin/bash
    

    进入容器后启动nginx服务:

     此时访问对应的网址就可以看到如下页面:

     说明nginx启动成功!

    启动一个Django容器

    docker run -it -p 8081:8000 --name server01 django /bin/bash

    进入容器后,启动一个django项目:

    django-admin startproject sayhello 

    进入sayhello目录下创建一个application

    python manage.py startapp app

    启动django项目,检查是否启动成功

    python manage.py runserver 0.0.0.0:8000

    分别在容器内部和本地都访问成功!

    在app的views.py中编写相应的视图函数,添加以下内容:

    1. import os
    2. from django.http import HttpResponse
    3. def get_host_name(request):
    4. host_name = os.environ.get('HOSTNAME', 'None')
    5. info = f'您当前访问的主机是:{host_name}'
    6. return HttpResponse(info)

    在sayhello的urls中添加一条路由规则

     编辑sayhello下的settings文件,允许所有主机访问:

     执行迁移

    1. python manage.py makemigrations
    2. python manage.py migrate

    重启启动django,之后再访问sayhello这条路径,就会发现它返回了主机名!

     所以一台服务器部署成功!

    部署多台服务器

    1.打包一个容器

    #首先将上面部署好的django打包成一个镜像,之后直接启动即可!

    docker commit -a "LLL@2474605919@qq.com" -m "打包已经部署好的django项目,之后直接使用就行了。" aab53c10b632 mydjango:1.0

     2.开启多台服务

    1. docker run -it -p 8082:8000 --name server02 mydjango:1.0 /bin/bash
    2. docker run -it -p 8083:8000 --name server03 mydjango:1.0 /bin/bash
    3. docker run -it -p 8084:8000 --name server04 mydjango:1.0 /bin/bash
    4. docker run -it -p 8085:8000 --name server05 mydjango:1.0 /bin/bash
    5. docker run -it -p 8086:8000 --name server06 mydjango:1.0 /bin/bash

    3.在各个容器中启动django项目

    1. cd /usr/src/sayhello
    2. python manage.py runserver 0.0.0.0:8000

    nginx和6台django服务都启动成功!

     配置nginx文件实现反向代理和负载均衡

    在/etc/nginx目录下配置nginx.conf文件,添加如下内容:

    1. user nginx;
    2. worker_processes auto;
    3. error_log /var/log/nginx/error.log notice;
    4. pid /var/run/nginx.pid;
    5. events {
    6. worker_connections 1024;
    7. }
    8. http {
    9. include /etc/nginx/mime.types;
    10. default_type application/octet-stream;
    11. log_format main '$remote_addr - $remote_user [$time_local] "$request" '
    12. '$status $body_bytes_sent "$http_referer" '
    13. '"$http_user_agent" "$http_x_forwarded_for"';
    14. access_log /var/log/nginx/access.log main;
    15. sendfile on;
    16. #tcp_nopush on;
    17. keepalive_timeout 65;
    18. #gzip on;
    19. upstream myserver {
    20. server 172.18.0.2:8000 weight=1;
    21. server 172.18.0.7:8000 weight=1;
    22. server 172.18.0.6:8000 weight=1;
    23. server 172.18.0.5:8000 weight=1;
    24. server 172.18.0.4:8000 weight=1;
    25. server 172.18.0.3:8000 weight=1;
    26. }
    27. upstream myserver2 {
    28. server 172.17.28.61:8081 weight=1;
    29. server 172.17.28.61:8082 weight=1;
    30. server 172.17.28.61:8083 weight=1;
    31. server 172.17.28.61:8084 weight=1;
    32. server 172.17.28.61:8085 weight=1;
    33. server 172.17.28.61:8086 weight=1;
    34. }
    35. server {
    36. listen 80;
    37. server_name localhost;
    38. location /sayhello {
    39. proxy_pass http://myserver2;
    40. }
    41. }
    42. include /etc/nginx/conf.d/*.conf;
    43. }

     负载均衡的核心配置就是upstream和proxy_pass这两项,在upstream中可以配置我们用来做负载均衡的服务器(也就是请求最后打到的真实服务器!,同时,如果当前nginx和不在这些服务器中,也就相当于同时做了反向代理!),当然,这里也可以指定做这个负载均衡的具体方法,我这里就是为每个服务器赋一个权重,权重越高的,命中的概率就越高。之后就是配置proxy_pass,只要保证代理的名称和刚刚配置的upstream名称一直就行。

    检验

    将上面的配置文件修改完成后,使用命令重新加载配置文件:

    nginx -s reload #对配置文件进行重新加载

    在没有配置出错的前提下应该就可以访问成功了!在此之前,我们还是先理一下逻辑,我们绑定了那么多ip和端口,如果不理清楚,都不知道该访问哪个了!

    首先,我们为每一个django服务都分配了一个容器,在各自的容器中,它们都使用的是8000端口,然后我们又为每一个容器映射了一个本地端口,因此,不管是通过本地ip+映射的端口还是容器ip+8000 ,是都能访问得到的!然后我们又开启了一个容器来做nginx服务,我们使用本地端口7777(已添加到安全组)映射了nginx容器的80端口,然后在nginx中做了负载均衡,所以我们只需要访问7777端口,就会把请求打到nginx容器的80端口,然后再通过负载均衡,打到对应的django服务中!

    因此,我们只需要访问通过公网ip+7777端口应该就能访问到啦!

    访问地址:

    http://www.lll.plus:7777/sayhello/ 

    可以看到,基本上前六次,每次的访问结果都不一样,第七次访问了第一次访问的服务,因为我为每一个服务配置的权重都是一样的,所以这和预期的结果也基本上是一直的!也算是大功告成啦!

    配置负载均衡的其他方法

    除了我上面使用的赋权重方法以外,还有其他的方法。

    1.轮询(默认)

    • 请求被平均调度给多个服务器处理
    1. http {
    2. ...
    3. upstream myserver {
    4. server 192.168.1.2:8080;
    5. server 192.168.1.3:8080;
    6. ...
    7. }
    8. server {
    9. ...
    10. location / {
    11. proxy_pass http://myserver;
    12. }
    13. }
    14. }

    2.加权轮询算法

    • 给服务器列表的每个服务器都增加一个权重,权重高者,命中率越高。
    1. http {
    2. ...
    3. upstream myserver {
    4. server 192.168.1.2:8080 weight=10;
    5. server 192.168.1.3:8080 weight=90;
    6. ...
    7. }
    8. ...
    9. server {
    10. ...
    11. localtion / {
    12. proxy_pass http:myserver;
    13. }
    14. }
    15. }

    3.ip_hash算法

    • 将客户端的ip进行hash运算,再根据运算结果打到某一台服务器,之后也会一直打到同一台服务器,可以解决session问题
    1. http {
    2. ...
    3. upstream myserver {
    4. ip_hash;
    5. server 192.168.1.2:8080;
    6. server 192.168.1.3:8080;
    7. ...
    8. }
    9. ...
    10. server {
    11. ...
    12. location / {
    13. proxy_pass http://myserver;
    14. }
    15. }
    16. }

    4.最少连接数算法

    • 此种方式nginx会将请求转发到当前连接数较少的服务器
    1. http {
    2. ...
    3. upstream myserver {
    4. least_conn;
    5. server 192.168.1.2:8080;
    6. server 192.168.1.3:8080;
    7. ...
    8. }
    9. ...
    10. server {
    11. ...
    12. location / {
    13. proxy_pass http://myserver;
    14. }
    15. }
    16. }

    5.url_hash算法

    • 对客户端请求的url进行hash运算,将相同的url打到同一个服务器
    • 需要安装url_hash补丁
    1. http {
    2. ...
    3. upstream myserver {
    4. server 192.168.1.2:8080;
    5. server 192.168.1.3:8080;
    6. ...
    7. hash $request_uri;
    8. hash_method crc32;
    9. }
    10. ...
    11. server {
    12. ...
    13. location / {
    14. proxy_pass http://myserver;
    15. }
    16. }
    17. }

    6.fair算法

    • 优先选择响应时间最短的服务器
    • 需要安装模块:nginx-upstream-fair-master
    1. http {
    2. ...
    3. upstream myserver {
    4. fair;
    5. server 192.168.1.2:8080;
    6. server 192.168.1.3:8080;
    7. ...
    8. }
    9. ...
    10. server {
    11. ...
    12. location / {
    13. proxy_pass http://myserver;
    14. }
    15. }
    16. }

    参考链接:nginx配置负载均衡

    同步更新于个人博客系统:使用nginx+docker实现一个简单的负载均衡​​​​​​​

  • 相关阅读:
    面试算法15:字符串中的所有变位词
    “突然降级到 iPhone 11 Pro Max 的我,好像……也没有错过什么?”
    用 p5.js 写个五子棋
    从本地到Gitee:一步步学习文件上传及解决常见报错问题
    14.9 Socket 高效文件传输
    .NET Worker Service 作为 Windows 服务运行及优雅退出改进
    linux安装oracle jdk
    2023-09-21 buildroot linux 查看应用的log打印信息,命令cat /var/log/messages
    ubuntu/linux系统知识(30)ubuntu系统配置项dconf/gsettings
    2. 计算虚拟化简介
  • 原文地址:https://blog.csdn.net/max_LLL/article/details/126320880