一、Nginx 介绍
Nginx (发音同 engine x)是一款高性能的 HTTP 和 反向代理 服务器国内使用nginx Web服务器的网站有:新浪、网易、 腾讯等。
二、Tomcat 介绍
Tomcat是Apache 软件基金会(Apache Software Foundation)的Jakarta 项目中的一个核心项目,由Apache、Sun 和其他一些公司及个人共同开发而成。由于有了Sun 的参与和支持,最新的Servlet 和JSP 规范总是能在Tomcat 中得到体现,Tomcat 5支持最新的Servlet 2.4 和JSP 2.0 规范。因为Tomcat 技术先进、性能稳定,而且免费,因而深受Java 爱好者的喜爱并得到了部分软件开发商的认可,成为目前比较流行的Web 应用服务器。目前最新版本是8.0。
三、MemCached 介绍
Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。
四、实验环境:物理机:192.168.126.1 win7
虚拟机: 192.168.126.15 CentOS-5.5
在物理主机上安装Nginx服务,memcached服务,配置Tomcat-台端口8080
在虚拟机上配置一台Tomcat 端口8080
熟悉Linux的朋友也可在Linux上搭建Nginx + memcached 服务
download Tomcat: http://mirror.esocc.com/apache/tomcat/tomcat-7/v7.0.54/bin/apache-tomcat-7.0.54-windows-x86.zip
五、准备一个java web小项目测试本人此处项目名为Session
将些项目发布到物理机Tomcat 192.168.126.1:8080 和虚拟机Tomcat 192.168.126.15:8080 注意端口不能是80,80端口由nginx服务器代理。
项目结构:一个实体User类,一个LoginServlet类处理登录请求,一个login.jsp登录页面,一个success.jsp登录成功页面
package com.rx.vo;
import java.io.Serializable;
public class User implements Serializable{
private static final long serialVersionUID = 7073950136835429991L;
private String userId;
private String username;
private String password;
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
public User(String userId, String username, String password) {
super();
this.userId = userId;
this.username = username;
this.password = password;
}
}
package com.rx.servlet;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.rx.vo.User;
@WebServlet(name = "LoginServlet" , urlPatterns = "/loginServlet.do")
public class LoginServlet extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = -6451894481175083005L;
private static Map<String,User> users = new HashMap<String,User>();
private static Log LOG = LogFactory.getLog(LoginServlet.class);
static {
users.put("tom", new User("1001", "tom", "123456"));
users.put("king", new User("1002", "king", "123456"));
users.put("sam", new User("1003", "sam", "123456"));
users.put("jack", new User("1004", "jack", "123456"));
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String userName = request.getParameter("userName");
String password = request.getParameter("password");
LOG.info("Raw input:userName=" + userName + ",password=" + password);
String url = request.getContextPath();
LOG.info("URL------>>" + url);
if(userName!=null && password!=null
&& users.containsKey(userName)
&& users.get(userName).getPassword().equals(password)) {
LOG.info("Login;status=SUCCESS");
HttpSession session = request.getSession();
session.setAttribute("SESSION_USER", users.get(userName));
LOG.info("SessionID----->>" + session.getId());
response.sendRedirect(url + "/success.jsp");
} else {
LOG.info("Login;status=FAIL");
request.getRequestDispatcher("login.jsp").forward(request, response);
}
}
}
login.jsp页面内容如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>登录页面</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<link rel="stylesheet" type="text/css" href="css/main.css"></link>
</head>
<%
String ip = request.getLocalAddr();
String id = session.getId();
%>
<body>
<form method="post" action="loginServlet.do">
<table class="table">
<tr>
<td colspan="2">
<b>SESSION_ID = <%=id %></b>
</td>
</tr>
<tr>
<td height="15" colspan="2">
<b><%=ip %> 用户登录</b>
</td>
</tr>
<tr>
<td width="80"><b>用户名</b></td>
<td><input type="text" name="userName" value="" /></td>
</tr>
<tr>
<td><b>密 码</b></td>
<td><input type="password" name="password" value="" /></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="登 录" />
<input type="reset" value="重 置" />
</td>
</tr>
</table>
</form>
</body>
</html>
success.jsp内容如下:
<%@ page language="java" import="com.rx.vo.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>登录成功页面</title>
<link rel="stylesheet" type="text/css" href="css/main.css"></link>
</head>
<%
User user = (User) session.getAttribute("SESSION_USER");
String ip = request.getLocalAddr();
String id = session.getId();
String username = "";
if (user != null) {
username = user.getUserId() + "------->>" + user.getUsername() + "----->>" + user.getPassword();
}
%>
<body>
<h2 class="title"><%=ip %> 服务器处理结果 SESSIONID = <%=id %> </h2>
<h2 class="title">当前登录用户:<%=username %> <a href="index.html">主页</a></h2>
</body>
</html>
六、download Nginx: http://nginx.org/download/nginx-1.6.0.zip 目前最新版本是nginx-1.7.1
并解压到E:\nginx-1.6.0目录中,在命令提示窗口中进入到E:\nginx-1.6.0目录
nginx.exe #启动nginx服务
nginx -s stop #停止nginx服务
nginx -s reload #重新启动nginx
nginx -s quit #退出nginx
nginx -t #检测配置文件的正确性
启动Nginx后输入http://127.0.0.1/ 可以看到nginx的欢迎页面了,非常友好
接下来配置配置Nginx负载均衡,我的目录在E:\nginx-1.6.0\conf\nginx.conf以下是我简单配置
#是注释内容,配置文件修改完成后启动两台Tomcat服务,然后重新启动Nginx服务。
输入:http://127.0.0.1/Session/login.jsp
响应结果:
192.168.126.1 用户登录
再次刷新:
192.168.126.15 用户登录
证明Nginx反向代理和负载均衡配置成功了。
#user nobody; #用户
worker_processes 1; #工作进程,根据硬件调整,大于等于CPU核数
#error_log logs/error.log; #错误日志配置
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid; #pid放置位置
events {
#use epoll;
#使用epoll的I/O 模型
# 补充说明:
#与apache相类,nginx针对不同的操作系统,有不同的事件模型
#A)标准事件模型
#Select、poll属于标准事件模型,如果当前系统不存在更有效的方法,nginx会选择select或poll
#B)高效事件模型
#Kqueue:使用于FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X.使用双处理器的MacOS #X系统使用kqueue可能会造成内核崩溃。
#Epoll:使用于Linux内核2.6版本及以后的系统。
#/dev/poll:使用于Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。
#Eventport:使用于Solaris 10. 为了防止出现内核崩溃的问题, 有必要安装安全补丁
worker_connections 1024;
#工作进程的最大连接数量,根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行
#每个进程允许的最多连接数, 理论上每台nginx服务器的最大连接数为worker_processes*worker_connections
keepalive_timeout 60;
}
#设定http服务器,利用它的反向代理功能提供负载均衡支持
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
#配置两台Tomcat真实服务器
upstream B2C_WEB {
#ip_hash; #目的保证客户端的ip地址不变,请求就只送到固定的一个Tomcat处理
server 192.168.126.1:8080 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.126.15:8080 weight=1 max_fails=3 fail_timeout=30s;
#weight=1表示
#这表示,如果服务器192.168.126.1 | 15在30秒内出现了3次错误,
#那么就认为这个服务器工作不正常,从而在接下来的30秒内nginx不再去访问这个服务器。
}
server {
listen 80; #监听端口
server_name localhost;
charset UTF-8;
index index.html index.htm index.jsp index.do;
root E:\\JavaEE\\Apache-Tomcat-7.0.41\\wtpwebapps; #WEB服务的主目录
location ~ ^/(WEB-INF)/ {
deny all; #禁止访问WEB-INF目录
}
# 动态数据由代理服务器Tomcat处理
location ~ .*\.(jsp|jspx|do)?$ {
proxy_pass http://B2C;# 反向代理
proxy_set_header X-Real-IP $remote_addr;
proxy_next_upstream http_502 http_504 error timeout invalid_header;
}
# 静态数据直接读取不经过Tomcat服务器
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d; #在客户端保存时间
}
location ~ .*\.(js|css)?$
{
expires 1h;
}
# 监控Nginx服务状态
location /Nginxstatus {
stub_status on;
access_log off;
}
#charset koi8-r;
#access_log logs/host.access.log main;
#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;
}
}
}
七、download Memcached: 官方并未提供memcached windows版本 自己到网上找memcached-1.2.6-win32-bin.zip或
memcached-win32-1.4.4-14.zip下载
八、memcached安装步骤:
①.解压到指定目录,如E:\memcached\
②.打开 开始 —>> 运行 —>> cmd 调出命令窗口,进入到memcached的解压目录
③.安装memcached: 输入E:\memcached\memcached.exe -d install 执行安装
注意事项根据下载版本不同安装文件可能是单文件,不用质疑。
④.启动memcached服务:输入E:\memcached\memcached.exe -d start 启动服务
设置memcached,启动该服务后,memcached服务默认占用的端口是11211,占用的最大内存默认是64M。
如果需要修改这两个参数,比如修改端口为10000,内存为512,则输入:
E:\memcached\memcached.exe -p 10000 -m 512 -d start , -p 表示要修改的端口,-m表示占用的最大内存(单位为M)。
⑤.参数介绍在安装和启动时可设置如下参数:
-p 监听的端口
-l 连接的IP地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间,key+value+flags默认是48
-h 显示帮助
连接memcached服务器:telnet 192.168.1.120 11211
输入stats查看基本信息:
STAT pid 1712
STAT uptime 5247
STAT time 1402624936
STAT version 1.2.6
STAT pointer_size 32
STAT curr_items 0
STAT total_items 0
STAT bytes 0
STAT curr_connections 3
STAT total_connections 5
STAT connection_structures 4
STAT cmd_get 0
STAT cmd_set 0
STAT get_hits 0
STAT get_misses 0
STAT evictions 0
STAT bytes_read 221
STAT bytes_written 512
STAT limit_maxbytes 67108864
STAT threads 1
⑤.停止memcached服务: 输入E:\memcached\memcached.exe -d stop|shutdown 进行关闭。
九、配置Session共享
①.这里需要使用一个开源项目,即Memcached Session Manager(MSM),如下链接是该开源项目的官网:
http://code.google.com/p/memcached-session-manager/
官方给出4种序列化方案,其中kryo是效率最高的,我下载的是javolution序列化方案jar包
javolution-5.4.3.1.jar
memcached-session-manager-1.6.1.jar
memcached-session-manager-tc7-1.6.1.jar #Tomcat6 则用memcached-session-manager-tc6-1.5.1.jar
msm-javolution-serializer-1.6.1.jar
msm-javolution-serializer-cglib-1.3.0.jar
msm-javolution-serializer-jodatime-1.3.0.jar
spymemcached-2.7.3.jar
②.将上面所述的MSG的jar包拷贝至Tomcat安装目录lib文件夹中
编辑Tomcat E:\JavaEE\Apache-Tomcat-7.0.41\conf\context.xml配置文件
在
注意此处:memcachedNodes=”n1:localhost:11211” #将localhost换成实际启动了memcached服务的主机IP
③.测试项目:http://127.0.0.1/Session/login.jsp 登录成功页面返回结果如下:
192.168.126.1 服务器处理结果 SESSIONID = 2C33E37DD3EC70F1D1D66BA31D45970A-n1
当前登录用户:1001——->>tom—–>>123456
刷新页面返回结果如下:
192.168.126.15 服务器处理结果 SESSIONID = 2C33E37DD3EC70F1D1D66BA31D45970A-n1
当前登录用户:1001——->>tom—–>>123456
处理请求的服务器IP变化了,SESSION_ID保持一致,并且SESSION中保存的用户信息未失效说明SESSION共享成功。
到此利用Nginx + Tomcat + Memcached 搭建WEB服务器负载均衡SESSION失效转移成功。