我先来说一下简单的配置nginx转发吧。
首先,把我们的tomcat项目配置三个,并行启动在本地。端口分别为:8080、8180、8280
然后,安装nginx,具体步骤如下:
下载链接
安装命令 ./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里面的,现在遇到了问题。三台机器轮询是不同的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;
}
}
这样就实现了集群分布式项目用户登录信息的统一。
(这个策略曾经在我的某次作业中使用,现在拿出来分享以下这个策略。文章可能写的不是很好,,,但是自认为思想还是不错的
)