当前位置: 首页 > 编程日记 > 正文

nginx+tomcat+memcache实现负载均衡、session共享

实验架构图:

Table of Contents

1、配置tomcat

2、安装memcache

3、查看tomcat和memcache是否配置好

4、nginx实现负载均衡:

5、客户端进行测试:

6、验证结论:

7、总结:


实验环境

linux  redhat6.5   防火墙关闭,三台虚拟机和一台物理机

                  主机

                      操作系统

                           IP地址

                nginx

    

redhat6.5

test1:  172.25.1.11

              tomcat1  

                        test2:  172.25.1.12

              tomcat2  

                        test3:  172.25.1.13

            memcache1

                        test2:  172.25.1.12

            memcache2

                        test3:  172.25.1.13

解释: nginx做为反向代理,实现静动分离,将客户动态请求根据权重随机分配给两台tomcat服务器,memcache做为两台tomcat的共享session数据服务器。

1、配置tomcat

在test2和test3分别配置tomcat服务(这里只演示test2的配置,配置有区别的地方已经用红色标出来)

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

[root@test2 ~]# tar zxf jdk-7u79-linux-x64.tar.gz -C /usr/local
[root@test2 ~]# ln -s /usr/local/jdk1.7.0_79/ /usr/local/jdk
[root@test2 ~]# vim /etc/profile

export JAVA_HOME=/usr/local/jdk
export CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$PATH:$JAVA_HOME/bin

[root@test2 ~]# source /etc/profile             //刷新环境变量

[root@test2 ~]# which java             //查看java路径
/usr/local/jdk/bin/java
[root@test2 ~]# which javac
/usr/local/jdk/bin/java

此时java环境就搭建好了

[root@test2 ~]# vim test.java            //写一个java程序试试看能否运行,内容如下:

public class test
{
        public static void main(String[] args)
        {
                System.out.println("hello world");
        }
}

[root@test2 ~]# javac test.java          //进行编译
[root@test2 ~]# java test             //运行java

此时我们安装tomcat

[root@test2 ~]# tar zxf apache-tomcat-7.0.37.tar.gz -C /usr/local/
[root@test2 ~]# cd /usr/local/
[root@test2 local]# ln -s apache-tomcat-7.0.37/ tomcat              //做个软链接

[root@test2 local]# cd tomcat/apache-tomcat-7.0.37/

[root@test2 apache-tomcat-7.0.37]# mv * ..

[root@test2 apache-tomcat-7.0.37]# cd

session 的序列化方案官方推荐的有 4 种:
1. java serialization
2. msm-kryo-serializer
3. msm-javolution-serializer
4. msm-xstream-serializer
其中性能最好的序列化方案是 Kryo,此实验我们采用 kryo 方式

把如下jar软件包下载好放置到/usr/local/tomcat/lib 目录中,jar软件包包含如下内容:

[root@test2 jar]# cd
[root@test2 ~]# mv jar/  /usr/local/tomcat/lib
[root@test2 ~]# cd /usr/local/tomcat/lib/jar/
[root@test2 jar]# mv * ..
[root@test2 jar]# cd ..
[root@test2 lib]# ls

[root@test2 ~]# rm -rf jar

[root@test2 ~]# vim /usr/local/tomcat/conf/context.xml                 //配置memcache缓存

......

<Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
  memcachedNodes="n1:172.25.1.12:11211,n2:172.25.1.13:11211" //memcache的两个节点,11211是memcache的端口号
    failoverNodes="n1"             //test3和test2的区别是在这里写n2
      requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
        transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
          />
</Context>

[root@test2 local]# cd tomcat/
[root@test2 tomcat]# bin/startup.sh                 //开启tomcat服务; /usr/local/tomcat/bin/shutdown.sh 为关闭tomcat服务

   //查看tomcat的端口号

此时,浏览器分别输入test2和test3对应的ip及服务端口号8080进行查看:

均可以访问到,此时test2和test3两主机的tomcat服务就搭建完成啦。

温馨提示:如果访问时出现网页空白的情况,可以尝试用ps命令查看tomcat(java)的进程id号,然后kill -9 id 将进程杀掉,然后重启服务,再次查看应该就可以了,网页还是出不来你可以先将配置memcache的配置文件刚才添加的内容删掉,看是否可以访问,若可以,则说明是配置文件添加的内容的问题;若不能访问,则是下载过程中的问题。

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

2、安装memcache

test2和test3上执行:

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""'

[root@test2 ~]# yum install -y memcache

[root@test2 ~]# /etc/init.d/memcached start

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

3、查看tomcat和memcache是否配置好

[root@test2 ~]# cd /usr/local/tomcat/logs/
[root@test2 logs]# > catalina.out
[root@test2 logs]# cd -
/usr/local/tomcat
[root@test2 tomcat]# ./bin/startup.sh
Using CATALINA_BASE:   /usr/local/tomcat
Using CATALINA_HOME:   /usr/local/tomcat
Using CATALINA_TMPDIR: /usr/local/tomcat/temp
Using JRE_HOME:        /usr/local/jdk
Using CLASSPATH:       /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar
[root@test2 tomcat]# cd -
/usr/local/tomcat/logs
[root@test2 logs]# cat catalina.out                    //看到如下结果,说明已经配置成功

4、nginx实现负载均衡:

用nginx默认自带的proxy和upstream模块来实现后端web负载均衡,用nginx的sticky模块实现session共享

这里要用到sticky模块,所以提前下载nginx及nginx-sticky-module压缩包,进行源码编译,具体步骤看上一篇博客的后半片(扩展模块sticky部分),这里不再赘述。

上文博客连接:https://blog.csdn.net/weixin_41922887/article/details/89421210

只在test1上进行:

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

[root@test1 ~]# useradd -s /sbin/nologin nginx                //创建nginx程序用户,编译的时候用到

[root@test1 ~]# id nginx

nginx已经实现sticky模块的负载均衡

[root@test1 ~]# /opt/nginx/sbin/nginx -t                 //查看nginx的状态

修改配置文件

[root@test1 ~]# vim /opt/nginx/conf/nginx.conf

user  nginx   nginx;                                 //刚才创建的nginx用户

worker_processes  2;
events {
    worker_connections  65535;
}

http {
    upstream server {
    sticky;                             //sticky模块,目的是当同一个用户动态访问时将请求发到同一个tomcat上,实现session的共享
    server 172.25.1.12:8080;
    server 172.25.1.13:8080;
    }
    include       mime.types;
    default_type  application/octet-stream;

sendfile        on;
    keepalive_timeout  65;

#gzip  on;

server{
        listen       80;
        server_name  www.westos.org;                         //访问时的域名
    location / {
              root   html;
              index  index.html index.htm;
    }
        location ~ \.jsp$ {                                                //所有 jsp 页面交给 tomcat 处理,动静分离
                proxy_pass http://server;
    }

error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

[root@test1 ~]# /opt/nginx/sbin/nginx -t            //检查语法是否有错误

[root@test1 ~]# /opt/nginx/sbin/nginx           //开启服务

此时,我们的所有服务就搭建完成了。

5、客户端进行测试:

测试nginx服务:

静态测试:

在test1上执行:

[root@test1 ~]# cd /opt/nginx/html/                   //nginx的默认发布路径
[root@test1 html]# ls
50x.html index.html
[root@test1 html]# vim cxx.html                     //写一个静态的文件cxx.html
<h1>it's a static nginx</h1>

此时在网页进行测试:

动态测试:
test2和test3都执行(这里只演示test2):

[root@test2 ~]# cd /usr/local/tomcat/webapps/ROOT/
[root@test2 ROOT]# vim test.jsp

The time is:<%=new java.util.Date() %>

客户端进行访问:

再如:

[root@test2 ROOT]# vim cxx.jsp

<%@ page contentType="text/html; charset=GBK" %>
<%@ page import="java.util.*" %>
<html><head><title>Cluster App Test</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
<%
out.println("<br> ID " + session.getId()+"<br>");
String dataName = request.getParameter("dataName");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
}
out.print("<b>Session list</b>");
Enumeration e = session.getAttributeNames();
while (e.hasMoreElements()) {
String name = (String)e.nextElement();
String value = session.getAttribute(name).toString();
out.println( name + " = " + value+"<br>");
System.out.println( name + " = " + value);
}
%>
%<form action="test.jsp" method="POST">
%name:<input type=text size=20 name="dataName">
%<br>
%key:<input type=text size=20 name="dataValue">
%<br>
%<input type=submit>
%</form>
%</body>
%</html>

[root@test2 ROOT]# scp westos.jsp root@test3:/usr/local/tomcat/webapps/ROOT      //test2和test3同时添加,scp直接发过去就好

可以看出,访问动态页面时用到后端服务器,这里接受访问请求的是test2,对应的memcache是test3

也可以看出,不管怎么刷新或者重新访问,只要是同一台主机,则接受请求的服务器不会变,和第一次访问时是同一台服务器。

6、验证结论:

现在将test3的memcache服务关闭并进行刷新操作,则此时:

[root@test3 tomcat]# /etc/init.d/memcached stop           //可以看出此时memcache变为test2节点,而请求还是会交给test2的 tomcat,没有因为test3的memcache挂掉而丢掉

将test3的memcache恢复状态

[root@test3 tomcat]# /etc/init.d/memcached start

刷新时memcache不会变回去

此时将test2的tomcat服务宕掉,并刷新:

[root@test2 tomcat]# /usr/local/tomcat/bin/shutdown.sh

访问结果为:

此时,memcache仍然为test2

7、总结:

不同的主机访问时会调度到不同的 tomcat 实例上处理,来自同一主机的请求会交给同一个 tomcat 实例处理,此时你 down 掉当前正在响应的 tomcat 实例,nginx 会自动把用户的请求调度到另一个 tomcat 实例上,同时 session 也没有丢掉。

原理:当test2中tomcat宕机后,test3接管会话后从本地的memcache处读取memcache的信息。

           当test2的memcache宕机后,test3的tomcat中会将会话信息存至本地,以致session不会丢失。

相关文章:

(转)二叉树系列面试问题

转自 &#xff1a;http://blog.csdn.net/luckyxiaoqiang/article/details/7518888/ 版权所有&#xff0c;转载请注明出处&#xff0c;谢谢&#xff01;http://blog.csdn.net/walkinginthewind/article/details/7518888 树是一种比较重要的数据结构&#xff0c;尤其是二叉树。二…

百度UEditor开发案例(JSP)

本案例的开发环境&#xff1a;MyEclipsetomcatjdk 本案例的开发内容&#xff1a;用百度编辑器发布新闻&#xff08;UEditor的初始化开发部署&#xff09;编辑已发过的新闻&#xff08;UEditor的应用——编辑旧文章&#xff09;上传附件、图片等 由于百度编辑器强大的功能&a…

iOS中的动力学:Dynamics【1】

iOS7建议我们创建的界面具有物理特性&#xff0c;而不只是像素的集合&#xff0c;可以响应触摸、手势、屏幕方向改变等事件&#xff0c;让用户与界面之间有更深入的交互&#xff0c;而不是像iOS6那样在软件界面上模仿现实世界的纹理而已。或许你会认为创建感觉上真实的界面比创…

自动化运维工具Saltstack(一)

1、saltstack简介&#xff1a; 什么是saltstack&#xff1f; saltstack是基于python开发的一套C/S架构配置管理工具 使用SSL证书签方的方式进行认证管理 号称世界上最快的消息队列ZeroMQ使得SaltStack能快速在成千上万台机器上进行各种操作 采用RSA Key方式确认身份 传输采用AE…

【UIDynamic例子】挂起的方块

通过前面的动力学小Demo&#xff08;本文默认你已经看过这篇Blog&#xff1a;传送门&#xff09;&#xff0c;我们对UIKit中的UIDynamic已经有了初步的认识。现在我们写个更加有趣的Demo&#xff1a;模拟一个用弹性绳子挂起的小方块&#xff0c;用户可以将它拖动到屏幕任意位置…

IIS7 配置PHP服务器

安装PHP Manager&#xff1a; 1&#xff09;访问 http://phpmanager.codeplex.com/releases/view/69115 下载PHP Manager。其中&#xff0c;x86 为32位 Windows 系统使用&#xff0c;x64 为64位 Windows 系统使用&#xff0c;请根据使用的 Windows 系统情况下载 2&#xff09;下…

在文本框中提示用户输入内容格式的方法

希望达到的效果&#xff1a; 方法一&#xff1a;鼠标点击文本框时文字消失 <input id"login_name" type"text" οnblur"javascript:check_login_name();" οnfοcus"if(this.value支持英文及数字组合) this.value;this.style.color#000&…

saltstack实现haproxy+keepalived负载均衡+高可用(二)

一键部署haproxykeepalived实现负载均衡高可用 实验环境&#xff1a; &#xff01;&#xff01;&#xff01;&#xff01; 特别注意&#xff1a; www.westos.org为test1的minion名字 test1: 172.25.1.11 nginx master minion test2: 172.25.…

iOS开发技巧(系列十八:扩展UIColor,支持十六进制颜色设置)

新建一个Category&#xff0c;命名为UIColorHex&#xff0c;表示UIColor支持十六进制Hex颜色设置。 UIColorHex.h文件&#xff0c; #import <UIKit/UIKit.h> #define RGBA_COLOR(R, G, B, A) [UIColor colorWithRed:((R) / 255.0f) green:((G) / 255.0f) blue:((B) / 255…

iOS顶部菜单栏

封装的一个顶部菜单栏&#xff0c;使用懒加载&#xff08;选择后加载当前页及前后各一页&#xff09;&#xff0c;自适应标题长度。 下载&#xff1a; Github&#xff1a;https://github.com/dolacmeng/JXChannelSegment 用法&#xff1a; //init Segment segment [[JXSegme…

Mac环境下svn的使用

CHENYILONG BlogMac环境下svn的使用 Mac环境下svn的使用 在Windows环境中&#xff0c;我们一般使用TortoiseSVN来搭建svn环境。在Mac环境下&#xff0c;由于Mac自带了svn的服务器端和客户端功能&#xff0c;所以我们可以在不装任何第三方软件的前提下使用svn功能&#xff0c;不…

zabbix简介及基本安装(一)

zabbix简单介绍&#xff1a; 官网&#xff1a;可以进官网查看一下&#xff1a;https://www.zabbix.com/cn/ //英语能力有限的读者可以将由上角的语言调成汉语方便查看 功能&#xff1a;网络监控、服务器监控、云监控、服务监控等。 介绍&#xff1a;zabbix&#xff08;[…

顺序表应用6:有序顺序表查询

顺序表应用6&#xff1a;有序顺序表查询 Time Limit: 7MS Memory Limit: 700KBSubmit StatisticProblem Description 顺序表内按照由小到大的次序存放着n个互不相同的整数&#xff08;1<n<20000)&#xff0c;任意输入一个整数&#xff0c;判断该整数在顺序表中是否存在。…

LA 5717枚举+最小生成树回路性质

1 /*LA 57172 《训练指南》P3433 最小生成树的回路性质4 在生成的最小生成树上&#xff0c;新增一条边e(u,v)5 若原图上u到v的路径的最大边大于e&#xff0c;则删除此边&#xff0c;加上e&#xff0c;否则不变。6 7 若原图上u到v的路径的最大边的产生&#xff1a;BFS/DFS都可 &…

【Runtime】动态添加方法demo

今天写一个小demo来演示下runtime的消息转发和动态添加方法。 一般项目中都会有保存当前登录用户资料的需求&#xff0c;我们可以直接将登录成功后的用户信息分别保存到NSUserDefaults中&#xff1a; [def setObject:"JackXu" forKey:"UserName"];[def set…

Zabbix之主机的添加与删除(二)

接着上一篇内容继续讲&#xff1a; 环境等都是建立在上一篇内容的基础上的&#xff0c;见https://blog.csdn.net/weixin_41922887/article/details/83755271 redhat6 test1: 172.25.1.11 zabbix-agent redhat7 server: 172.25.1.1 …

昨天网上感觉好冷,睡在席子上都是感觉打哈欠

今天爸妈也是休息一天&#xff0c;中午听说是要到外婆家去&#xff0c;不过家里就不知道会不会有一个团圆聚餐了&#xff0c;还有伴月就是国庆解&#xff0c;那时就要吧这个推掉值班的事情做好下。 转载于:https://www.cnblogs.com/bkchengzheng/p/5874328.html

几行代码实现神奇移动的过渡动画

1.效果如图&#xff1a; 2.实现&#xff1a; 假设需求为如上图&#xff0c;点击ViewController01后&#xff0c;ViewController01上的两张图片&#xff0c;移动到ViewContoller02中&#xff0c;其实两个ViewController的View上分别放置了这两张图&#xff0c;JXMagicMove就是实…

php字符串处理函数相关操作

<?php//获取tech和98426这两个字符串$str "http://info.meadin.com/tech/98426_1.shtml";echo $newstr substr($str,7,strlen($str)); //info.meadin.com/tech/98426_1.shtml$arr explode(/,$newstr);$num $arr[1];//tech$user strstr($arr[2], _, true); /…

介绍Zabbix的两种监控模式(主动模式和被动模式)

Zabbix agent检测分为两种模式&#xff1a;主动模式和被动模式 被动模式&#xff0c;也是默认的Zabbix监控模式&#xff0c;被动模式是相对于proxy来说的。proxy主动发送数据就是主动模式&#xff0c;proxy等待server的请求再发送数据就是被动模式。主动模式有个好处就是可以有…

【Step By Step】将Dotnet Core部署到Docker下

一、使用.Net Core构建WebAPI并访问Docker中的Mysql数据库 这个的过程大概与我之前的文章《尝试.Net Core—使用.Net Core Entity FrameWork Core构建WebAPI&#xff08;一&#xff09;》一致。 但是在我们这里&#xff0c;由于docker中无法部署sql server&#xff0c;所以我采…

ipad无法与itunes同步,提示因为这台电脑不再被授权使用在此ipad上购买的项目解决方案...

1、iOS设备用数据线连接到电脑&#xff1b;2、打开电脑上的iTunes 11&#xff0c;按CtrlB键调出菜单栏&#xff0c;按CtrlS键调出边栏&#xff1b;在边栏的 设备 下面看到你的iOS设备&#xff1b;3、点击菜单栏中的商店&#xff0c;点击 对这台电脑授权&#xff0c;输入你的App…

iOS根据字节数截取字符串

最近项目有个需求&#xff0c;文章的作者最多显示7个中文字&#xff0c;英文字符算半个中文字&#xff0c;超过7个中文字&#xff0c;则显示&#xff1a;前7个中文字...&#xff0c;使用NSString的length方法&#xff0c;不管是一个中文还是英文字符&#xff0c;都是返回1。因此…

搭建Zabbix分布式监控

1、实现zabbix监控nginx 实验环境&#xff1a; server1 172.25.1.1 server redhat7 test1 172.25.1.11 agent redhat7 在“手动添加”主机的基础上进行扩展 开启服务&#xff1a; [rootserver ~]# systemctl…

Codeforces Round #372 (Div. 2), problem: (B) Complete the Word

水题&#xff0c;每次截取长度为26的字符串&#xff0c;然后直接进行修改就可以 然而本弱渣昨天wa看很久 include<bits/stdc.h> using namespace std; int n,c; int ans[30]; int main() { string s; cin>>s; int tt0; int ns.size(); if(n<26) { cout<<&…

百练 2973 Skew数 解题报告

思路&#xff1a; 计算出每一个skew数的不同位数表示的权值&#xff0c;然后用该位与权值相乘。用int数组来装权值&#xff0c;用char数组来装skew数。 代码&#xff1a; #include<stdio.h> #include<string.h> int main() {int i, k, sum;int base[32];char skew[…

【Python】在Mac系统中安装Pygame

我们通过Homebrew来安装Pygame&#xff0c;Homebrew是Mac OSX上的软件包管理工具&#xff0c;如果还没安装Homebrew&#xff0c;将以下命令粘贴至终端先安装Homebrew /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install…

zabbix部署onealert云警告平台

onealert告警功能 告警 All In One&#xff0c;支持微信、邮箱、短信、APP、电话告警支持接入 Zabbix、Nagios、阿里云、腾讯云、监控宝等等告警信息灵活的分配策略&#xff0c;可灵活的分配告警信息发送给相关人员微信、邮箱、app 等告警方式全部免费实验环境&#xff1a; 首…

StringBuilder、StringBuffer、String区别

相信大家对 String 和 StringBuffer 的区别也已经很了解了&#xff0c;但是估计还是会有很多同志对这两个类的工作原理有些不清楚的地方&#xff0c;今天重新把这个概念给大家复习一下&#xff0c;顺便牵出 J2SE5.0 里面带来的一个新的字符操作的类—— StringBuilder &#xf…

Class中isAssignableFrom() 方法

看Spring源码的时候看到这个方法&#xff1a; 1 protected WebApplicationContext createWebApplicationContext(ServletContext sc) { 2 Class<?> contextClass determineContextClass(sc); 3 if (!ConfigurableWebApplicationContext.class.isAs…