• Ngnix + Tomcat负载均衡架构


    一、nginx

    Nginx (发音同 engine x)是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。  其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页伺服器中表现较好。目前中国大陆使用nginx网站用户有:新浪、网易、 腾讯,另外知名的微网志Plurk也使用nginx。

    废话不多说, 先上图...

    二、Tomcat

    tomcat服务器就不用多说了吧。我们可以准备2、3个tomcat服务器进行测试。废话不多说,准备环境走起...

    三、环境准备 

    1、 jdk 1.8.0_102

    2、nginx 1.12.0(在官网上下一个解压就行,官网:http://nginx.org/);

    3、2个或多个tomcat 6.x 7.x 8.x 9.x 都可以(比如我准备的是3个一模一样的8.x版本,只是配置文件改了而已,一会会详细怎么改 ,官网:http://tomcat.apache.org/)

    四、nginx配置文件

    路径: ginx-1.12.0conf ginx.conf

    配置如下:



     [html]
     view plain copy
     
    1. #Nginx所用用户和组,window下不指定
      #user  niumd niumd;
      #工作的子进程数量(通常等于CPU数量或者2倍于CPU)
      worker_processes  2;
      #错误日志存放路径
      #error_log  logs/error.log;
      #error_log  logs/error.log  notice;
      error_log  logs/error.log  info;
      #指定pid存放文件
      #pid        logs/nginx.pid;
       
      events {
      #使用网络IO模型linux建议epoll,FreeBSD建议采用kqueue,window下不指定。
      #use epoll;
      #允许最大连接数
      worker_connections  2048;
      }
       
      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  off;
       
      access_log  logs/access.log;
       
      client_header_timeout  3m;
      client_body_timeout    3m;
      send_timeout           3m;
      client_header_buffer_size    1k;
      large_client_header_buffers  4 4k;
      sendfile        on;
      tcp_nopush      on;
      tcp_nodelay     on;
      #keepalive_timeout  75 20;
      #include    gzip.conf;
       
      #负载均衡配置
      upstream localhost {
      #根据ip计算将请求分配各那个后端tomcat,许多人误认为可以解决session问题,其实并不能。
      #同一机器在多网情况下,路由切换,ip可能不同
      #ip_hash;
      #upstream的负载均衡,weight是权重,可以根据机器配置定义权重。weigth参数表示权值,权值越高被分配到的几率越大。
      ip_hash;
      server localhost:18081;
      server localhost:18082;
      server localhost:18083;
       
      #nginx的upstream目前支持4种方式的分配
              #1、轮询(默认)
              #每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。
              #2、weight
              #指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。
              #例如:
              #upstream bakend {
              #    server 192.168.0.14 weight=10;
              #    server 192.168.0.15 weight=10;
              #}
              #2、ip_hash
              #每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题。
              #例如:
              #upstream bakend {
              #    ip_hash;
              #    server 192.168.0.14:88;
              #    server 192.168.0.15:80;
              #}
              #3、fair(第三方)
              #按后端服务器的响应时间来分配请求,响应时间短的优先分配。
              #upstream backend {
              #    server server1;
              #    server server2;
              #    fair;
              #}
              #4、url_hash(第三方)
              #按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
              #例:在upstream中加入hash语句,server语句中不能写入weight等其他的参数,hash_method是使用的hash算法
              #upstream backend {
              #    server squid1:3128;
              #    server squid2:3128;
              #    hash $request_uri;
              #    hash_method crc32;
              #}
       
              #tips:
              #upstream bakend{#定义负载均衡设备的Ip及设备状态}{
              #    ip_hash;
              #    server 127.0.0.1:9090 down;
              #    server 127.0.0.1:8080 weight=2;
              #    server 127.0.0.1:6060;
              #    server 127.0.0.1:7070 backup;
              #}
              #在需要使用负载均衡的server中增加 proxy_pass http://bakend/;
       
              #每个设备的状态设置为:
              #1.down表示单前的server暂时不参与负载
              #2.weight为weight越大,负载的权重就越大。
              #3.max_fails:允许请求失败的次数默认为1.当超过最大次数时,返回proxy_next_upstream模块定义的错误
              #4.fail_timeout:max_fails次失败后,暂停的时间。
              #5.backup: 其它所有的非backup机器down或者忙的时候,请求backup机器。所以这台机器压力会最轻。
       
              #nginx支持同时设置多组的负载均衡,用来给不用的server来使用。
              #client_body_in_file_only设置为On 可以讲client post过来的数据记录到文件中用来做debug
              #client_body_temp_path设置记录文件的目录 可以设置最多3层目录
              #location对URL进行匹配.可以进行重定向或者进行新的代理 负载均衡
      }
      server {
      listen       80;
      server_name  localhost;
      location / {
      proxy_connect_timeout   3;
      proxy_send_timeout      30;
      proxy_read_timeout      30;
      proxy_pass http://localhost;
      }
       
      #css|js|ico|gif|jpg|jpeg|png|txt|html|htm|xml|swf|wav这些都是静态文件,但应分辨,js、css可能经常会变,过期时间应小一些,图片、html基本不变,过期时间可以设长一些
              location ~* ^.+.(ico|gif|jpg|jpeg|png|html|htm)$ {
                  root         html;
                  access_log   logs/access.log;
                  expires      -1s;
              }
       
      gzip on;
              gzip_comp_level 7;
              gzip_min_length  1100; #需要压缩的最小长度
              gzip_buffers    4 8k;
              gzip_types      text/plain application/javascript text/css text/xml application/x-httpd-php; #指定需要压缩的文件类型
              output_buffers  1 32k;
              postpone_output  1460;
       
              #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;
              }
      }
      }
    2.  

    五、Tomcat配置文件

    apache-tomcat-8.5.16.1confserver.xml

    ... 

     <Server port="18006" shutdown="SHUTDOWN">

    ...

    <Connector port="18081" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> 

    ...

    <Connector port="18009" protocol="AJP/1.3" redirectPort="8443" /> 

     ...

     apache-tomcat-8.5.16.2confserver.xml

     ...

    <Server port="18007" shutdown="SHUTDOWN"> 

     ...

    <Connector port="18082" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> 

    ...

    <Connector port="28009" protocol="AJP/1.3" redirectPort="8443" /> 

    ...

    apache-tomcat-8.5.16.3confserver.xml

     ...

    <Server port="18008" shutdown="SHUTDOWN"> 

    ...

    <Connector port="18083" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" /> 

     ...

     <Connector port="38009" protocol="AJP/1.3" redirectPort="8443" />

    ...

     

    OK,需要配置的就配置好了,我们再做一件事,我们选用欢迎页,为了区别欢迎页,我们修改一下index.jsp页面,apache-tomcat-8.5.16.1webappsROOTindex.jsp,随意区分一下就好。然后分别启动nginx和三个tomcat(nginx.exe、startup.bat)

     

     

    (因为编译器不让我放图片,放一个网上找的,真的日狗,在网页上复制图片粘贴可以,更日血的是,自己写一个简单静态页面加载截图不能复制图片粘贴。。。)

    因为我们在上面说了,改tomcat的欢迎页,所以每次刷新的时候呢,三个欢迎页就会轮流替换,在实际项目中也是一样的原理,但是有一点不足,session共享问题,这么做session是不共享的。也是不满足高并发,这只是一个演示的demo。

    怎样实现session共享呢?
     
     

     查了一些资料,看了一些别人写的文档,总结如下,实现nginx session的共享

    服务器有多台,用nginx做负载均衡,这样同一个IP访问同一个页面会被分配到不同的服务器上,如果session不同步的话,就会出现很多问题,比如说最常见的登录状态,下面提供了几种方式来解决session共享的问题:

    1、不使用session,换用cookie session是存放在服务器端的,cookie是存放在客户端的,我们可以把用户访问页面产生的session放到cookie里面,就是以cookie为中转站。你访问web服务器A,产生了session然后把它放到cookie里面,当你的请求被分配到B服务器时,服务器B先判断服务器有没有这个session,如果没有,再去看看客户端的cookie里面有没有这个session,如果也没有,说明session真的不存,如果cookie里面有,就把cookie里面的sessoin同步到服务器B,这样就可以实现session的同步了。

    说明:这种方法实现起来简单,方便,也不会加大数据库的负担,但是如果客户端把cookie禁掉了的话,那么session就无从同步了,这样会给网站带来损失;cookie的安全性不高,虽然它已经加了密,但是还是可以伪造的。

    2、session存在数据库(MySQL等)中 后台可以配置将session保存在数据库中,这种方法是把存放session的表和其他数据库表放在一起,如果mysql也做了集群了话,每个mysql节点都要有这张表,并且这张session表的数据表要实时同步。

    说明:用数据库来同步session,会加大数据库的IO,增加数据库的负担。而且数据库读写速度较慢,不利于session的适时同步。

    3、session存在memcache或者Redis中 memcache可以做分布式,配置文件中设置存储方式为memcache,这样会建立一个session集群,将session数据存储在memcache中。

    说明:以这种方式来同步session,不会加大数据库的负担,并且安全性比用cookie大大的提高,把session放到内存里面,比从文件中读取要快很多。但是memcache把内存分成很多种规格的存储块,有块就有大小,这种方式也就决定了,memcache不能完全利用内存,会产生内存碎片,如果存储块不足,还会产生内存溢出。

    4、nginx中的ip_hash技术能够将某个ip的请求定向到同一台后端,这样一来这个ip下的某个客户端和某个后端就能建立起稳固的session,ip_hash是在upstream配置中定义的:

    [html] view plain copy
     
    1. upstream localhost  
    2.     {   
    3.              server localhost:18006;   
    4.              server localhost:18007;  
    5.              ip_hash;  
    6.     }  
    7.     server  
    8.     {  
    9.              listen 80;  
    10.              location /  
    11.              {  
    12.                      proxy_pass  
    13.                     localhost;  
    14.              }  
    15.  }  

    ip_hash是容易理解的,但是因为仅仅能用ip这个因子来分配后端,因此ip_hash是有缺陷的,不能在一些情况下使用:

    1.nginx不是最前端的服务器。 ip_hash要求nginx一定是最前端的服务器,否则nginx得不到正确ip,就不能根据ip作hash。譬如使用的是squid为最前端,那么nginx取ip时只能得到squid的服务器ip地址,用这个地址来作分流是肯定错乱的。

    2.nginx的后端还有其它方式的负载均衡。 假如nginx后端又有其它负载均衡,将请求又通过另外的方式分流了,那么某个客户端的请求肯定不能定位到同一台session应用服务器上。这么算起来,nginx后端只能直接指向应用服务器,或者再搭一个squid,然后指向应用服务器。最好的办法是用 location作一次分流,将需要session的部分请求通过ip_hash分流,剩下的走其它后端去。

    5、upstream_hash 为了解决ip_hash的一些问题,可以使用upstream_hash这个第三方模块,这个模块多数情况下是用作url_hash的,但是并不妨碍将它用来做session共享。它的原理是这样的:浏览器A去访问nginx,nginx根据IP的hash去访问某一个服务器,至此,以后的每次访问都会是这个服务器在运作,所以才有的session同步,浏览器B、C、D...也去访问nginx,nginx还会根据B、C、D的IP_hash访问的服务器可能还是原来的服务器也有可能是新的服务器。它们之后的访问都会是各自第一次访问你的服务器,只有服务器崩了,才会去别的服务器,从而实现session共享。

  • 相关阅读:
    CodeForces 156B Suspects(枚举)
    CodeForces 156A Message(暴力)
    CodeForces 157B Trace
    CodeForces 157A Game Outcome
    HDU 3578 Greedy Tino(双塔DP)
    POJ 2609 Ferry Loading(双塔DP)
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛 19000互质的个数
    Java 第十一届 蓝桥杯 省模拟赛十六进制转换成十进制
  • 原文地址:https://www.cnblogs.com/wwjldm/p/8610587.html
Copyright © 2020-2023  润新知