Nginx+Sping Could+Tomcat 实现负载均衡

一、什么是Nginx?

     Nginx是一款轻量级高性能的反向代理服务器,支持Web站点和邮件代理。其特点是内存少,并发能力强,结构简单,支持长时间的动作,它通过代理模式将用户的请求转发给不同的服务器,减轻服务器的压力。

二、Nginx负载均衡策略

      Nginx支持6种负载均策略,分别为轮询,权重,IP hash(ip 分配),least_conn(最少连接),fair(响应时间),url_hash(url分配)。通过这几种策略来达到不同的业务。下面分别介绍下各自的特点:

1、轮询

     轮询是策略中最基础的方式,通过upstream模块实现默认的均衡策略 如图:

    upstream weburl{
        server 127.0.0.1:8080;
        server 127.0.0.1:8081 backup;//IP + 端口 +参数配置
    }

    以上通过upstram模块 指定后端的服务器列表,每个请求会按时间顺序访问后端的服务器。其中提供一些参数设置:

    fail_timeout :时间超出。

    max_timeout  : 最超时时间次数,如超过次数会被认为该服务器为停机状态。

    fail_time:请求超时的时间 默认为10s。

    backup:标记为该服务为务用服务器,当其中的主机死机后,请求后被备用机接收。

    down:表示永远停机。

 2、权重策略Weight

    权重策略是增加请求次数的几率,可以设置对哪台服务器进行多次的访问:

   upstream weburl{
        server 127.0.0.1:8080 weight=2;
        server 127.0.0.1:8081 weight=1;
        server 127.0.0.1:8082 backup;
    }

 上面的例子中使用weight参数=2来表示应该服务器的请求次数会比权重1的要访问的次数高一些,权重分配的越高处理请求次数越多,此策略用于服务器之间配置较大时进行使用可以和least_conn,ip_hash配合使用。

3、IP_Hash策略

  ip_hash策略指定负载均衡按照基于客户端IP的分配方式,将相同的客户端请求发送到同一个服务器进行处理
  upstream weburl{
        ip_hash;
        server 127.0.0.1:8080 weight=2;
        server 127.0.0.1:8081 weight=1;
        server 127.0.0.1:8082 ;
   }

  其中ip_hash不能和backup进行同时使用,些策略适合有状态服务(session)。

4、least_conn策略

least_conn策略是将请求交给后端连接数较少的服务器,轮询策略中是将请求平均的分配给后端服务器,这会增加占用请求的时间,least_conn比轮询效果会好一些。

  upstream weburl{
        least_conn;
        server 127.0.0.1:8080 weight=2;
        server 127.0.0.1:8081 weight=1;
        server 127.0.0.1:8082 ;
   }

5、第三方策略fair

      要实现这种策略需要安装第三方插件。

     upstream weburl{
        server 127.0.0.1:8080 weight=2;
        server 127.0.0.1:8081 weight=1;
        server 127.0.0.1:8082;
        fair;
    }

  fair是按照服务器响应时间来进行分配请求,响应时间短的优先分配。

6、url_hash策略

 url_hash也是需要第三方插件,url_hash是根据url的hash结果值来分配后端服务器,当多个请求都访问同一个资源,使用url_hash策略可以将同一台服务器之前访问过的资源进行再次分配,从缓存中取出。

    upstream weburl{
        hash $request_url;
        server 127.0.0.1:8080 weight=2;
        server 127.0.0.1:8081 weight=1;
        server 127.0.0.1:8082;
    }

以上几种策略要根据不同的应用场景进行使用。

三、Nginx如何处理请求

      Nginx在启动会解析配置文件,得到需要的端口和IP地址,然后在nginx的主进程里,发先初始化这个监控对象socket绑定到指定的IP地址端口再进行监听listen,然后再通过fork创建一个新的进程worker,多个worker进程之间会相互竟争accept的连接,此时,客户端可以向nginx发起连接,与nginx三次握手(http协议),找到一适合的进程进行连接同时会获得accept的对象(socket),然后创建nginx封装ngx_connection结构体,之后处理之间的读写请求操作进行数据交换,完成之后再进行释放连接。

      对于超时的请求nginx会根据设置的超时时间来进行设定,长时间没有得到处理会返回一个状态码(404  501)来标明这个请求出现了错误,nginx提供proxy_next_upstream_tries来进行重试机制,出现了超时的主机,不会再次发送到该主机上,由下一个竟争的节点来进行处理。其中在nginx之前还有一层代理SLB最大的超时时间为一分钟,如果设置多了,会出现多次重复请求的问题。

四、搭建Nginx代理服务器

       本文以windows做一个简单的示例,Linux的请查看其它文章。

    1、首先从官网下载最新的tar包(http://nginx.org/en/download.html)。

    2、下载完后解压一个盘符下打开confg 下的nginx.conf文件如图:


#user  nobody;
worker_processes  2;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
	multi_accept on;
	accept_mutex on;
	
}


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  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    #gzip  on;

	upstream weburl{
	
		server 127.0.0.1:8080 weight=2;
		server 127.0.0.1:8081 weight=1;
		server 127.0.0.1:8082;
		
	}
	
	error_page 400 http://www.baidu.com;
	
    server {
        listen       80;
        server_name  localhost;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
			proxy_pass http://weburl;
            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       8888 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;
    #    }
    #}

}

有些参数是修改过的。

查看文件的模块结构:

**************************************

全局变量

events{   //nginx与网络连接配置参数

}

http{    //http模块

     //局部参数

    server{  //服务器模块

        location{  //服务地址参数

       }  

 }

}

*****************************

这以上为主要的几个模块。后面再来进行相关配置。

五、打包SpringCould

   基于之前的文章使用到的 Spring-cloud-mybatis-jsp 工程 在index.jsp增加一个h1标签来进行标识哪个站点。在工程中复制一份工程。复制工程之后需要修改几个地方

1、是pom.xml 

	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.2.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>spring-cloud-mybatis-jsp2</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>spring-cloud-mybatis-jsp2</name>
	<description>Demo project for Spring Boot</description>

修改其中的artifactId  和 name值  内容为新的项目名称

2、在工程空间下修改.settings文件下org.eclipse.wst.common.component 文件将其中的deploy-name,context-root,java-output-path都修改成新的工程名称

<?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">
    <wb-module deploy-name="spring-cloud-mybatis-jsp2-0.0.1-SNAPSHOT">
        <wb-resource deploy-path="/" source-path="/target/m2e-wtp/web-resources"/>
        <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>
        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/java"/>
        <wb-resource deploy-path="/WEB-INF/classes" source-path="/src/main/resources"/>
        <property name="context-root" value="spring-cloud-mybatis-jsp2"/>
        <property name="java-output-path" value="/spring-cloud-mybatis-jsp2/target/classes"/>
    </wb-module>
</project-modules>

3、打包成war文件  首先pom.xml里的<packaging>war</packaging>需要指定的是war值,然后文件中的tomcat需要设置<scope>provided</scope>值

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>

 最后主程序需要继承SpringBootServletInitializer类重写configure方法 如下:

@SpringBootApplication
public class SpringCloudMybatisJspApplication extends SpringBootServletInitializer {

	public static void main(String[] args) {
		SpringApplication.run(SpringCloudMybatisJspApplication.class, args);
	}
	
	@Override//为了打包springboot项目
    protected SpringApplicationBuilder configure(
            SpringApplicationBuilder builder) {
        return builder.sources(this.getClass());
    }

}

满足这几个条件就可以进行war打包, 点击工程  右键选择Run As->Maven install 之后console会显示打包war后的路径 eg:

E:\apache-maven-3.5.3\maven\repository\com\example\spring-cloud-mybatis-jsp2\0.0.1-SNAPSHOT\spring-cloud-mybatis-jsp2-0.0.1-SNAPSHOT.war

之后将文件重命为相同的名称放在tomcat webapp目录。另一个工程同样的方法进行打包。

注意:test文件下的内容不能进行打包,删除就可以了。

4、设置两个Tomcat

      从安装好的Tomcat复制一份,修改tomcat的配置文件 主要修改三个地方:

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

  <Connector port="8081" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
   <Connector port="8010" protocol="AJP/1.3" redirectPort="8443" />

然后修改bin目录下的两个文件:startup.bat 和catalina.bat 将其中的CATALINA_HOME全替换为新的名称CATALINA_HOME_8080  另一个tomcat就取CATALINA_HOME_8081。

最后运行两个tomcat,tomcat会自动的将war进行解压运行   如图 :

        

两个一样的tomcat 只是端口不一样,访问同一个程序。

6、配置Nginx

       上面的显示例代码也已经出给了,下在进行说明一下,在server 模块的上方通过upstream 服务群名称来指定不同的服务器:

       upstream weburl{
        server 127.0.0.1:8080 weight=2;
        server 127.0.0.1:8081 weight=1;
    }

 其中server可以指定本机和其它的IP地址,端口就是tomcat的端口号,后面参数可以设置均衡策略。其中在localtion模块中需要将刚刚配置的集群名字放到服务地上模块中进行指定。如图:

        location / {
            proxy_pass http://weburl;
            root   html;
            index  index.html index.htm;
        }

以上就配置好了,本例只是个简单的例子,还是其它的配置比如超时,文件缓存策略、重试等。

之后启动Nginx 使用命令start nginx启动(nginx -s stop 停止),如果出现错误就查看log文件下的error.log文件,里面指明错误的信息,如果没有错误说明配置没有出现错误,查看进程里是否有nginx进程。

最后运行Url: http://localhost/spring-cloud-mybatis-jsp/getusers  连续刷新查看  通过nginx代理可以访问不同的工程,不需要指定端口号,应该都在nginx代理中进行分配了。

总结:

   以上就是本文通过Nginx+Spring Could+Tomcat实现一个简单的负载均衡,Nginx还有很多的配置但都是基于nginx.conf里的参数来进行设置,具体参数需要根据工程来进行设置,包括连接的优化,以及响应时间等等要根据实际情况而定。

猜你喜欢

转载自blog.csdn.net/looplook21/article/details/88366818