美文网首页
Nginx+SpringMVC 负载均衡中遇到的坑

Nginx+SpringMVC 负载均衡中遇到的坑

作者: IATNEH1900 | 来源:发表于2018-12-26 20:54 被阅读0次

    引言

    最近对公司的项目进行改造实施负载均衡,以便可以方便的进行横向扩展,提升性能,于是在项目中引入了SpringSession,来实现不同服务器上同一个项目的Session共享。

    改造过程

    由于项目较老,SpringMVC所使用的版本是3.1.4.RELEASE

    负载均衡

    1. 在pom.xml中引入SpringSession
            <!-- Jedis -->
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>2.9.0</version>
            </dependency>
            <!-- Spring Data Redis -->
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session-data-redis</artifactId>
                <version>1.2.1.RELEASE</version>
            </dependency>
            <!-- Spring Session -->
            <dependency>
                <groupId>org.springframework.session</groupId>
                <artifactId>spring-session</artifactId>
                <version>1.2.1.RELEASE</version>
            </dependency>
    
    1. application.xml中增加redis的配置
    
    
        <bean id="redisHttpSessionConfiguration" class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration">
            <property name="maxInactiveIntervalInSeconds" value="600" />
        </bean>
        <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
            <property name="maxTotal" value="100" />
            <property name="maxIdle" value="10" />
        </bean>
    
        <bean id="jedisConnectionFactory"
            class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
            destroy-method="destroy">
            <property name="hostName" value="${redis.host}" />
            <property name="password" value="${redis.pwd}" />
            <property name="port" value="${redis.port}" />
            <property name="database" value="${redis.database}" />
            <property name="usePool" value="true" />
            <property name="poolConfig" ref="jedisPoolConfig" />
        </bean>
    
    1. 修改web.xml新增过滤器
        <filter>
            <filter-name>springSessionRepositoryFilter</filter-name>
            <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>springSessionRepositoryFilter</filter-name>
            <url-pattern>/*</url-pattern>
            <dispatcher>REQUEST</dispatcher>
            <dispatcher>ERROR</dispatcher>
        </filter-mapping>
    
    1. Nginx配置改造
        upstream demo-site {
                server 192.168.0.1:86; #服务器A
                server 192.168.0.2:86; #服务器B
        }
        server {
            listen       80;
            server_name  host;
            location / {
                proxy_pass   http://demo-site;
            }
        }
    

    改造完毕后,通过域名访问项目,会轮询访问这两台服务器上的应用,Session也会在这两个应用上进行共享。

    文件共享

    两台服务器通过NFS协议挂载了同一个NAS云盘,路径统一为/nas,文件上传路径都配置这个路径就可以了。

    1. 前端的post请求 后端Controller中使用request.getInputStream()获取到流为空
    • 原因:SpringSession中获取SessionId的操作使用了request.getParameter()方法具体代码位置在CookieHttpSessionStrategy类中
        public String getRequestedSessionId(HttpServletRequest request) {
            Map<String, String> sessionIds = getSessionIds(request);
            String sessionAlias = getCurrentSessionAlias(request);
            return sessionIds.get(sessionAlias);
        }
    
        public String getCurrentSessionAlias(HttpServletRequest request) {
            if (this.sessionParam == null) {
                return DEFAULT_ALIAS;
            }
            String u = request.getParameter(this.sessionParam);
            if (u == null) {
                return DEFAULT_ALIAS;
            }
            if (!ALIAS_PATTERN.matcher(u).matches()) {
                return DEFAULT_ALIAS;
            }
            return u;
        }
    

    request.getParameter()操作会读取流信息,从而导致流被掏空,以致请求到达Controller时没数据可以读取。

    20160803175011173.jpg
    • 解决办法
      调用方使用接口时contentType 指定为'application/json;charset=UTF-8'或其它,只要不是application/x-www-form-urlencoded就可以
    1. Log日志写入混乱。
    • 应用使用Log4J记录日志,因为做了文件共享,所以考虑到日志查看方便,所以也都写到同一个文件,运行了几天才发现日志有丢失问题,估计是多个log4j进程同时写文件有冲突。
    • 解决方法
      日志配置中增加变量log4j.appender.E.File=/folder/path/info.${log4j.logtype}.log
      服务器A Tomcat配置bin/catalina.sh中增加参数JAVA_OPTS='-Xms512m -Xmx2048m -Dlog4j.logtype=1'
      服务器B Tomcat配置bin/catalina.sh中增加参数JAVA_OPTS='-Xms512m -Xmx2048m -Dlog4j.logtype=2'

    建议

    项目中尽量不要使用Application/Session存取数据。

    相关文章

      网友评论

          本文标题:Nginx+SpringMVC 负载均衡中遇到的坑

          本文链接:https://www.haomeiwen.com/subject/ylrklqtx.html