nginx+tomcat负载均衡、session处理策略

我先来说一下简单的配置nginx转发吧。

首先,把我们的tomcat项目配置三个,并行启动在本地。端口分别为:8080、8180、8280

然后,安装nginx,具体步骤如下:

下载链接
http://nginx.org/download/nginx-1.8.0.tar.gz

安装命令 ./cibfigure

安装pcre: yum -y install pcre pcre-devel
安装zlib: yum -y install zlib zlib-devel
./cibfigure
make
make install
验证是否安装成功:/usr/local/下有nginx文件夹
启动: /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
从容停止 kill -quit 进程号
查看ip端口: ps-ef grep nginx

配置文件在 安装目录/conf/nginx.conf
修改完后用/usr/local/nginx/sbin/nginx -s reload重新加载
负载均衡:
upstream colo {
server 127.0.0.1:8080;
server 127.0.0.1:8180;
server 127.0.0.1:8280;
}
location / {
#root html;
index index.html index.htm;
proxy_pass http://colo;
}
//路径错误解决
location / {
#root html;
#index index.html index.htm;
proxy_pass http://lib;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

三台tomcat启动后,启动nginx。
当你访问你的web项目的时候,轮训到那台tomcat就有日志刷出来。说明成功。
现在,我使用apache ab性能测试工具进行测试。(jvm、tomcat三台全都一样)性能结果提升如下:
nginx+tomcat负载均衡、session处理策略_第1张图片 nginx+tomcat负载均衡、session处理策略_第2张图片
nginx+tomcat集群部署还是比较容易的,但是,对于集群项目,我们的登录信息平时是保存在session里面的,现在遇到了问题。三台机器轮询是不同的session。这时,我的选择是,把用户登录信息保存在redis中,并且带有一个独一无二的key(uuid),然后呢,这个uuid对应的保存到用户浏览器的cookie中。
控制层代码(springmvc)代码如下:
package controller;

import java.util.UUID;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestMapping;

import entity.User;
import redis.clients.jedis.Jedis;
import service.UserService;
import utils.RedisUtil;
import utils.SerializeUtil;

/**
 * 
 * @author Yu Yufeng
 *
 */
@Controller
public class LoginController {

	@Autowired
	private UserService userService;

	/**
	 * 跳转到登录视图
	 * 
	 * @param session
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/login")
	public String loginUI(HttpSession session, Model model) throws Exception {
		return "login";
	}

	@RequestMapping("/quit")
	public String quit(HttpSession session, Model model, HttpServletResponse response,
			@CookieValue(value = "SESSIONUSER", required = false) String sessionUser) throws Exception {
		Cookie cookie = new Cookie("SESSIONUSER", null);
		Jedis jedis = RedisUtil.getJedis();
		jedis.del(sessionUser.getBytes());
		jedis.close();
		response.addCookie(cookie);
		return "redirect:login";
	}

	/**
	 * 跳转到注册视图
	 * 
	 * @param session
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/register")
	public String registerUI(HttpSession session, Model model) throws Exception {
		return "register";
	}

	/**
	 * 登录提交
	 * 
	 * @param session
	 * @param model
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("/login-sub")
	public String loginSubmit(HttpSession session, Model model, User user, HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		if (userService.checkUserPwd(user)) {
			User record = userService.getUserByName(user.getUserName());
			String uuid = UUID.randomUUID().toString();
			Jedis jedis = RedisUtil.getJedis();
			jedis.setex(("user_"+uuid).getBytes(), 1800, SerializeUtil.serialize(record));
			jedis.close();
			Cookie cookie = new Cookie("SESSIONUSER", "user_"+uuid);
			response.addCookie(cookie);
			return "redirect:user/main";
		} else {
			model.addAttribute("message", "登录失败,用户名或密码错误!");
			return "login";
		}
	}

	@RequestMapping("/register-sub")
	public String registerSubmit(HttpSession session, Model model, User user) throws Exception {
		User record = null;
		try {
			record = userService.register(user);
		} catch (Exception e) {
			model.addAttribute("message", "用户名已存在");
		}

		if (null != record) {
			model.addAttribute("user", record);
			model.addAttribute("message", "注册成功");
			return "login";
		}

		return "register";
	}
}

登录拦截:
package interceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import entity.User;
import redis.clients.jedis.Jedis;
import utils.RedisUtil;
import utils.SerializeUtil;

/**
 * 测试拦截器
 * 
 * @author yyf
 * 
 */
public class UserInterceptor implements HandlerInterceptor {

	// 执行Handler完成执行此方法
	// 应用场景:统一异常处理,统一日志处理
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object object,
			Exception exception) throws Exception {
	}

	// 进入Handler方法之后,返回modelAndView之前执行
	// 应用场景从模型出发 公用model数据(菜单导航)在这里传到视图,也可以在这里统一指定视图
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object object,
			ModelAndView modelAndView) throws Exception {
		Cookie[] cs = request.getCookies();
		for (Cookie c : cs) {
			if (c.getName().equals("SESSIONUSER")) {
				Jedis jedis = null;
				if (c.getValue() != null && !"".equals(c.getValue())) {
					try {
						jedis = RedisUtil.getJedis();
						byte[] userb = jedis.get((c.getValue()).getBytes());
						User user = (User) SerializeUtil.unserialize(userb);
						request.setAttribute("session_user", user);
						String sCart = "cartNumber_" + c.getValue();
						String n = jedis.get(sCart);
						if (n != null) {
							request.setAttribute("cart_quantity", n);
						}

					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						jedis.close();
					}
				}
			}
		}

	}

	// 进入Handler方法之前
	// 用于身份认真、身份授权
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {
		Cookie[] cs = request.getCookies();
		if (cs == null) {
			response.sendRedirect(request.getContextPath() + "/login");
			return false;
		}
		for (Cookie c : cs) {
			if (c.getName().equals("SESSIONUSER")) {
				if (c.getValue() != null && c.getValue() != null) {
					Jedis jedis = null;
					try {
						jedis = RedisUtil.getJedis();
						if (jedis.exists(c.getValue().getBytes())) {
							jedis.expire("cartNumber_" + c.getValue(), 1800);// 刷新redis时间
							jedis.expire("cart_" + c.getValue(), 1800);// 刷新redis时间
							jedis.expire(c.getValue(), 1800);// 刷新redis时间
							return true;
						} else {
							Cookie cook = new Cookie("SESSIONUSER", null);
							cook.setMaxAge(0);
							response.addCookie(cook);
						}
					} catch (Exception e) {
						e.printStackTrace();
					} finally {
						jedis.close();
					}

				}
			}
		}
		response.sendRedirect(request.getContextPath() + "/login");

		return false;
	}

}

这样就实现了集群分布式项目用户登录信息的统一。
(这个策略曾经在我的某次作业中使用,现在拿出来分享以下这个策略。文章可能写的不是很好,,,但是自认为思想还是不错的 )



你可能感兴趣的:(Java)