Tomcat多实例部署及其原理

导读:
昨天在跟群友作技术交流的时候,了解到,有不少大公司都是采用了高可用的,分布式的,实例沉余1+台。可是在小公司的同窗也不少,他们反映并非全部公司都有那样的资源来供你调度。每每公司只会给你一台机器,由于有些应用挂了公司也不会有损失的,咱们每每一台机器就能够搞定。
可是,咱们也要为咱们作出来的应用负责,毕竟东西作出来是为了给人用的,若是作出来的东西常常挂了,谈何使用,在前期,若是公司资源紧张的状况下,能够不能够作高可用,多机器的沉余部署。可是至少是在但机上有2个进程在跑。so,在这里咱们就说说这个,如何作单机多实例的部署。
在这里谈谈,在只有单机的资源下,如何把单机的资源压榨出来,用好单机。html

自家的主页: http://jbeacon.top/2016/11/19/yunwei/1/java

一、Tomcat部署的场景分析

一般,咱们对tomcat单机部署需求能够分为几种:mysql

  • 单实例单应用 (一个tomcat 一个web应用)
  • 单实例多应用 (一个tomcat多个应用)
  • 多实例单应用 (多个tomcat都部署一个应用)
  • 多实例多应用 (多个tomcat部署多个不一样的应用)

第一种场景:这是咱们开发中常常用到的,若是不要求周期性地维护tomcat版本,通常的作法是把打好的war包丢到webapps目录下,而后执行startup.sh脚本,而且能够在浏览器里访问就好了。
第二种场景:是把多个应用程序的war包放在同一个tomcat的webapps目录,这样一来,关闭和启动tomca,或tomcat挂掉会影响全部项目。
第三种场景: 各个tomcat都运行同一个应用程序,对应地须要修改不一样的监听端口,这种方式一般会和apache httpd或者nginx整合使用,作一些负载均衡的处理。
第四种场景: 至关于第一种场景的复数形式,除了修改不一样的监听端口,没有本质区别。linux

通常来讲,多实例部署tomcat,能够充分利用系统资源,不过这种方式,也有几个方面须要考虑:
多实例tomcat的更新维护,例如对tomcat进行升级等操做,咱们须要考虑如何能“优雅”地对全部实例进行升级
尽可能不要影响应用程序,在更新tomcat时,一不当心就把conf目录等所有覆盖,因此尽可能要把配置文件和安装目录隔离
对于单应用来讲,若是将war包分别置于各个tomcat的webapps目录,那么在发布新版本的war时,可能会出现某个实例更新失败,致使用户在访问时可能会访问到不一样版本的web app,所以,比较好的方式就是全部tomcat实例都统一指向同一个应用程序,这样作,就能够多个tomcat用一份应用源码,简单部署,单机高可用也能实现(要配合nginx).
本文重点阐述多实例应用的部署方案,可是为了解决上述几个问题,咱们须要先来了解一下tomcat的一些基本状况。nginx

二、咱们的目标

 

tomcat架构

 

三、tomcat架构

总体架构图

 

tomcat架构

 

这里有一台服务器,3台tomcat服务,以及一台tomcat的解构图。web

分离目录

目录 做用
bin 主要存放脚本文件,例如比较经常使用的windows和linux系统中启动和关闭脚本
conf 主要存放配置文件,其中最重要的两个配置文件是server.xml和web.xml
lib 主要存放tomcat运行所依赖的包
logs 主要存放运行时产生的日志文件,例如catalina.{date}.log等
temp 存放tomcat运行时产生的临时文件,例如开启了hibernate缓存的应用程序,会在该目录下生成一些文件
webapps 部署web应用程序的默认目录
work 主要存放由JSP文件生成的servlet(java文件以及最终编译生成的class文件)

再介绍两个tomcat中比较重要的概念(一般也是两个系统变量)——CATALINA_HOME和CATALINA_BASE:redis

CATALINA_HOME:即指向Tomcat安装路径的系统变量
CATALINA_BASE:即指向活跃配置路径的系统变量经过设置这两个变量,就能够将tomcat的安装目录和工做目录分离,从而实现tomcat多实例的部署。
Tomcat官方文档指出,CATALINA_HOME路径的路径下只须要包含bin和lib目录,这也就是支持tomcat软件运行的目录,而CATALINA_BASE设置的路径能够包括上述全部目录,不过其中bin和lib目录并非必需的,缺省时会使用CATALINA_HOME中的bin和conf。如此,咱们就可使用一个tomcat安装目录部署多个tomcat实例,这样的好处在于方便升级,就能够在不影响tomcat实例的前提下,替换掉CATALINA_HOME指定的tomcat安装目录。sql

 

tomcat架构

 

tomcat serve.xml 配置结构
Container容器子容器间关系图docker

tomcat架构

 

交互图shell

tomcat架构

 

对比下Tomcat serve.xml 的配置

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

 

<?xml version="1.0" encoding="UTF-8"?>

<Server port="8005" shutdown="SHUTDOWN">

<Listener className="org.apache.catalina.startup.VersionLoggerListener" />

<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />

<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

<GlobalNamingResources>

<Resource name="UserDatabase" auth="Container"

type="org.apache.catalina.UserDatabase"

description="User database that can be updated and saved"

factory="org.apache.catalina.users.MemoryUserDatabaseFactory"

pathname="conf/tomcat-users.xml" />

</GlobalNamingResources>

<Service name="Catalina">

<Connector port="8080" protocol="HTTP/1.1"

connectionTimeout="20000"

redirectPort="8443" />

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

<Engine name="Catalina" defaultHost="localhost">

<Realm className="org.apache.catalina.realm.LockOutRealm">

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"

resourceName="UserDatabase"/>

</Realm>

<Host name="localhost" appBase="webapps"

unpackWARs="true" autoDeploy="true">

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"

prefix="localhost_access_log" suffix=".txt"

pattern="%h %l %u %t &quot;%r&quot; %s %b" />

</Host>

</Engine>

</Service>

</Server>

 

四、实战

端口配置

修改server.xml

在server.xml中配置了四个监听端口,分别是:
Server Port:该端口用于监听关闭tomcat的shutdown命令,默认为8005.
Connector Port:该端口用于监听HTTP的请求,默认为8080.
AJP Port:该端口用于监听AJP( Apache JServ Protocol )协议上的请求,一般用于整合Apache Server等其余HTTP服务器,默认为8009
Redirect Port:重定向端口,出如今Connector配置中,若是该Connector仅支持非SSL的普通http请求,那么该端口会把https的请求转发到这个Redirect Port指定的端口,默认为8443

虚拟主机配置
再来讲Host配置,Host就是所谓的虚拟主机,对应包含了一个或者多个web应用程序,默认的Host配置以下

 

1

 

<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">

 

其中:
name: 虚拟主机的名称,一台主机表示了彻底限定的域名或IP地址,默认为localhost,同时也是惟一的host,进入tomcat的全部http请求都会映射到该主机上
appBase:web应用程序目录的路径,能够是CATALINA_HOME的相对路径,也能够写成绝对路径,默认状况下为$CATALINA_HOME/webappsunpackWARs: 表示是否自动解压war包
autoDeploy:所谓的热部署,即在tomcat正在运行的状况下,若是有新的war加入,则会当即执行部署操做
另外再介绍一个Host中的属性—deployOnStartup:表示tomcat启动时是否自动部署appBase目录下全部的Web应用程序,默认为true。这个属性和autoDeploy会产生两次部署的“反作用”:一次是tomcat启动时就开始部署,第二次就是autoDeploy引发的热部署。所以最好将autoDeploy置为false
在部署多实例单应用的时候,默认的$CATALINA/webapps会由于tomcat安装目录升级产生没必要要的麻烦,咱们考虑将appBase的目录统一到另外的路径下。

Context的配置
最后再说明一下Context的配置,它出如今Host配置内,一个Context的配置就表明了一个web应用程序,若是配置多应用程序,就须要在Host下配置多个Context,一个简单的Context配置以下

 

1

 

<Context path="/some" docBase="someapp.war" >

 

path:表示访问入口,例如,path=”/abc”,则访问localhost:8080/abc时,就能够访问该Context对应的应用程序。若是path=””,则直接用localhost:8080就能够访问
docBase:表示应用程序的解包目录或者war文件路径,是Host的appBase配置目录的相对路径,也能够是直接写成绝对路径,可是不要将appBase的值,做为docBase配置路径的前缀,例如appBase=”somedir”,docBase=”somedir-someapp.war”,这样的配置会致使部署错误
经过配置Host的appBase和Context的docBase两个属性,能够将应用程序的文件和tomcat相关的目录进行分离,这样webapps目录也就没有做用了。

跟我来实施该方案

  • 如今假设咱们有一台已经配置好Java环境的服务器:(我用的是阿里云)
  • 我已经有一个已经完成的shop.war 应用程序

步骤1:
下载并解压tomcat

tomcat架构

 

步骤2:
对Tomcat目录做如下调整:
在tomcat安装目录下建立a.ttlsa.com、b.ttlsa.com,而且将conf、logs、webapp、temp、work目录拷贝到这两个目录,而后tomcat安装目录只须要留下bin、a.ttlsa.com、b.ttlsa.com、lib这4个目录便可。配置后的目录结构以下:

tomcat架构

 

若是要度tomcat 进行升级,咱们只是须要对tomcat的lib 和 bin 目录进行升级便可。

步骤3:
配置站点server.xml
配置a.ttlsa.com 

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

 

<?xml version="1.0" encoding="UTF-8"?>

<!-- 8005 改成8005 -->

<Server port="8005" shutdown="SHUTDOWN">

<Listener className="org.apache.catalina.startup.VersionLoggerListener" />

<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />

<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

<GlobalNamingResources>

<Resource name="UserDatabase" auth="Container"

type="org.apache.catalina.UserDatabase"

description="User database that can be updated and saved"

factory="org.apache.catalina.users.MemoryUserDatabaseFactory"

pathname="conf/tomcat-users.xml" />

</GlobalNamingResources>

<Service name="Catalina">

<Connector port="8081" protocol="HTTP/1.1"

connectionTimeout="20000"

redirectPort="8443" />

<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->

<Engine name="Catalina" defaultHost="localhost">

<Realm className="org.apache.catalina.realm.LockOutRealm">

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"

resourceName="UserDatabase"/>

</Realm>

<!--

<Host name="localhost" appBase="webapps"

unpackWARs="true" autoDeploy="true">

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"

prefix="localhost_access_log" suffix=".txt"

pattern="%h %l %u %t &quot;%r&quot; %s %b" />

</Host>

-->

<Host name="localhost" appBase="F:\data\www\a.ttlsa.com"

unpackWARs="true" autoDeploy="true"

xmlValidation="false" xmlNamespaceAware="false">

<Context path="" docBase="" reloadable="true">

<valve className="org.apache.catalina.valves.RemoteAddrValve" />

</Context>

</Host>

</Engine>

</Service>

</Server>

 

配置b.ttlsa.com

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

 

<?xml version="1.0" encoding="UTF-8"?>

<!-- 8005 改成8006 -->

<Server port="8002" shutdown="SHUTDOWN">

<Listener className="org.apache.catalina.startup.VersionLoggerListener" />

<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />

<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />

<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />

<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />

<GlobalNamingResources>

<Resource name="UserDatabase" auth="Container"

type="org.apache.catalina.UserDatabase"

description="User database that can be updated and saved"

factory="org.apache.catalina.users.MemoryUserDatabaseFactory"

pathname="conf/tomcat-users.xml" />

</GlobalNamingResources>

<Service name="Catalina">

<Connector port="8082" protocol="HTTP/1.1"

connectionTimeout="20000"

redirectPort="8443" />

<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->

<Engine name="Catalina" defaultHost="localhost">

<Realm className="org.apache.catalina.realm.LockOutRealm">

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"

resourceName="UserDatabase"/>

</Realm>

<!--

<Host name="localhost" appBase="webapps"

unpackWARs="true" autoDeploy="true">

<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"

prefix="localhost_access_log" suffix=".txt"

pattern="%h %l %u %t &quot;%r&quot; %s %b" />

</Host>

-->

<Host name="localhost" appBase="F:\data\www\a.ttlsa.com"

unpackWARs="true" autoDeploy="true"

xmlValidation="false" xmlNamespaceAware="false">

<Context path="" docBase="" reloadable="true">

<valve className="org.apache.catalina.valves.RemoteAddrValve" />

</Context>

</Host>

</Engine>

</Service>

</Server>

 

建立多实例启动脚本

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

 

# description: 启动tomcat多实例.#

. /etc/init.d/functions

RETVAL=$?

# tomcat实例目录

export CATALINA_BASE="$PWD"

# tomcat安装目录

export CATALINA_HOME="/usr/local/tomcat-7.0.50"

# 可选

export JVM_OPTIONS="-Xms128m -Xmx1024m -XX:PermSize=128m -XX:MaxPermSize=512m"

case "$1" in

start)

if [ -f $CATALINA_HOME/bin/startup.sh ];then

echo $"Start Tomcat"

$CATALINA_HOME/bin/startup.sh

fi

;;

stop)

if [ -f $CATALINA_HOME/bin/shutdown.sh ];then

echo $"Stop Tomcat"

$CATALINA_HOME/bin/shutdown.sh

fi

;;

*)

echo $"Usage: $0 {start|stop}"

exit 1

;;

esac

exit $RETVAL

 

这段shell 脚本比较简单,主要是设置环境变量,接受命令参数 RETVAL=?,来执行不一样的命令。RETVAL=start/stop等exportCATALINABASE=”?,来执行不一样的命令。RETVAL=start/stop等exportCATALINABASE=”PWD” 表示设置当前路径为 CATALINA_BASE 的环境变量,通常状况下CATALINA_BASE 和 CATALINA_HOME 是默认同样的。

启动脚本赋权限

 

1

 

# chmod a+x tomcat.sh

 

五、启动测试

启动/关闭a.ttlsa.com

 

1

2

3

4

5

6

 

启动

# cd /usr/local/tomcat-7.0.50/a.ttlsa.com/

# ./tomcat.sh start

关闭

# cd /usr/local/tomcat-7.0.50/a.ttlsa.com/

# ./tomcat.sh stop

 

启动/关闭b.ttlsa.com

 

1

2

3

4

5

6

 

启动

# cd /usr/local/tomcat-7.0.50/a.ttlsa.com/

# ./tomcat.sh start

关闭

# cd /usr/local/tomcat-7.0.50/a.ttlsa.com/

# ./tomcat.sh stop

 

备注:必定须要cd到tomcat.sh的当前目录下执行才能够

在win7 下,须要建立在a.ttlsa.com 和b.ttlsa.com下面建立 startup.bat 来启动

 

1

2

3

4

5

6

 

@echo off

set JAVA_HOME=D:\Program Files\Java\jdk1.8.0_112

set PATH=%JAVA_HOME%\bin;%PATH%

set CATALINA_BASE=%CD%

cd E:\tomcat-8.5.6\bin

catalina.bat start

这段是在win7 下云的bat脚本,于shell脚本同理,set CATALINA_BASE=%CD% 也是设置环境变量,CD 能够获取当前的路径。

shell 脚本入门参考:http://sishuok.com/forum/blogPost/list/5655.html

六、结果

单个Tomcat应用多个tomcat实例的配置到此,就结束了。
此外,咱们在这里的基础上进行系统的扩展,好比若是个人Tomcat应用挂掉了,个人整个应用都将不可用了,咱们应该如何处理?
咱们能够把Tomcat复制多份,在单机的状况下,开多一个Tomcat进程,在配合Nginx 来配置,就能实现Tomcat的自动切换,这些内容,有空再写。

若是须要操做多个实例显得比较麻烦,你们能够自行写统一的脚本。

 

tomcat架构

 

tomcat架构

 

Linux 下的实现基本一致。

这样的好处是,显而易见的,这样能开启Tomcat的多个进程,即多台tomcat,挂了也不太怕,还有其余tomcat应用支撑,代码实例咱们发版本的时候,只须要发布一份,实例代码易于维护。
可是,咱们网站的域名和端口通常是同一采用80端口,统一的域名,而如今咱们开启tomcat只能一个使用80端口,显然是不合适的·,为此咱们会引入负载均衡的nginx来配置。
nginx 采用80 端口,tomcat分别采用8080, 8081, 8082 这样就能让咱们的程序稳定的运行。
这样,咱们就能进最大的限度来压榨单机的性能,保证应用程序的稳定的运行。
而然,单机否则有单机的瓶颈,毕竟单机中的cpu 已经各类硬件的限制,会大大影响实例程序的跑动,在这时,就再也不是单机能抗的动的了,咱们须要分析程序的瓶颈在那?数据库,那就把数据库单独分出去,单独一台机器,是文件图片服务器,就把他分出去。若是是应用程序太大,就要考虑把应用实例进行拆解为不一样哦那个的组件,单独部署,这就是分布式部署。
固然,这都是后话,只有程序复杂到必定的程度,并体量很大的话,才会作这种架构的演变,成本和技术投入的难度也会相应的变大。
本章,只局限于如何玩好单机的基础上来讨论,对于分布式的那块,笔者能力有限,尚且还不能彻底驾驭,不作分享。

七、nginx+tomcat热备

在上面的配置的基础上,咱们在进一步进行扩展,进行实例的均衡和热备。
能够在一个服务器挂了的状况下连到另一个,那怎么弄呢?
其实很简单,在upstream中的local_tomcat中配置多一个server。
在上面,个人a.ttlsa.com 和 b.ttlsa.com 都是访问 F:\data\www\a.ttlsa.com 下的源码的index.jsp 页面,
为了能观察,nginx 的keepAlive 的效果,我作一下修改:
a.ttlsa.com —> F:\data\www\a.ttlsa.com index.jsp 中文字是 1
b.ttlsa.com —> F:\data\www\b.ttlsa.com index.jsp 中文字是 2

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

 

upstream local_tomcat {

server localhost:8081 weight=1;

server localhost:8082 weight=5;

}

server {

listen 80;

server_name localhost:8081;

#charset koi8-r;

#access_log logs/host.access.log main;

#location / {

# root html;

# index index.html index.htm;

#}

location / {

proxy_pass http://local_tomcat;

}

 

tomcat架构

 

在一般的状况下,咱们通常是指向一份源码就足够了,而且设置权值,减轻应用的压力。同时也不会出现单点的状况。

补充:nginx.con 配置

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

 

#user nobody;

worker_processes 1;

events {

worker_connections 1024;

}

http {

include mime.types;

default_type application/octet-stream;

sendfile on;

#tcp_nopush on;

#keepalive_timeout 0;

keepalive_timeout 65;

#gzip on;

upstream local_tomcat {

server localhost:8081 weight=1;

server localhost:8082 weight=5;

}

server {

listen 80;

server_name localhost;

#charset koi8-r;

#access_log logs/host.access.log main;

#location / {

# root html;

# index index.html index.htm;

#}

location / {

proxy_pass http://local_tomcat;

}

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root html;

}

}

}

综上:咱们作到了多台tomcat 可是咱们也能作到tomcat的简单升级,而且实现实例的负载均衡,已经应用的主备,在也不用担忧应用挂掉而睡不了觉了。
缺点:nginx依然存在单点的问题。

本次的实验资源供下载:http://download.csdn.net/detail/a82793510/9687715

经验之谈

若是是在资源有限的状况下,已经选择了单机,证实不是有钱荏,我通常会把上面的权去掉,在这样咱们就能够在一台tomcat应用服务器挂掉的状况下,才会访问备机Tomcat应用服务器。
若是只是应用的状况下,这样已经足够了。用基于IP分发的策略已经能解决绝大部分需求。

资源进一步极端化

如今,咱们在这台单机上已经部署了一个应用app1, 假设如今我司实在是资源太紧缺了,咱们又要在这台机子上,部署另一个应用app2。
那么如今咱们就要对Nginx 和 Tomcat 进行改动。
改动通常分为2种方法:2级域名改动 或 2级目录改动。
先来在上面的基础上说说二级目录改动:
按照咱们上面的,咱们的目标的架构:咱们已经部署了一个应用程序:some.war ,如今我要采用二级目录方式部署另外的一个应用程序:app.war。
那么我会在上面的基础上作以下的修改:localhost 能够修改成本身的域名。

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

 

<Host name="localhost/some" appBase="F:\data\www\a.ttlsa.com"

unpackWARs="true" autoDeploy="true"

xmlValidation="false" xmlNamespaceAware="false">

<Context path="" docBase="" reloadable="true">

<valve className="org.apache.catalina.valves.RemoteAddrValve" />

</Context>

</Host>

<Host name="localhost/app" appBase="F:\data\www\b.ttlsa.com"

unpackWARs="true" autoDeploy="true"

xmlValidation="false" xmlNamespaceAware="false">

<Context path="" docBase="" reloadable="true">

<valve className="org.apache.catalina.valves.RemoteAddrValve" />

</Context>

</Host>

另外的一台的service.xml 也一样如此配置。
nginx中的localhost 能够修改成本身的域名 如 mp.hello.io

 

1

2

3

4

5

 

server {

listen 80;

server_name localhost; // 能够修改成本身的域名

}

二级域名的改动,
前提:咱们有一个顶级域名:如 hello.io 这样的一个顶级域名:
那么,咱们如今能够这样作:
如今万网中配置一下咱们的二级域名,如som.hello.io和app.hello.io 都要在万网中指向咱们的服务器Ip 地址。
在增长二级域名的状况下,咱们能够新增2个是实例。
把Nginx修改成这样的配置:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

 

#user nobody;

worker_processes 1;

events {

worker_connections 1024;

}

http {

include mime.types;

default_type application/octet-stream;

sendfile on;

#tcp_nopush on;

#keepalive_timeout 0;

keepalive_timeout 65;

#gzip on;

upstream local_tomcat01 {

server localhost:8081;

server localhost:8082;

}

upstream local_tomcat02 {

server localhost:8083;

server localhost:8084;

}

server {

listen 80;

server_name some.hello.io;

#charset koi8-r;

#access_log logs/host.access.log main;

#location / {

# root html;

# index index.html index.htm;

#}

location / {

proxy_pass http://local_tomcat02;

}

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root html;

}

}

server {

listen 80;

server_name app.hello.io;

#charset koi8-r;

#access_log logs/host.access.log main;

#location / {

# root html;

# index index.html index.htm;

#}

location / {

proxy_pass http://local_tomcat02;

}

error_page 500 502 503 504 /50x.html;

location = /50x.html {

root html;

}

}

此外,修改一下,Tomcat 的端口就能够了,同时80 81, 指向一个实例,83 84 指向另一个实例(appBase中指定)。这样就能够作到程序的主备操做。

备注:service_name 的名称能够是ip 地址。
nginx在配置upstream时,有两个参数:
ip_hash(同一IP一直使用同一台server服务)
weight(server的使用权重,数值越大,nginx分发的请求越多)

经过配合这两个参数,能粗糙地解决session共享的问题。
对于一些不是太依赖session的应用,或者只有用户登陆时保存,那么我认为能够用Cookies代替。
即便真的要Session共享,我认为手动写代码保存到Memcached比为Tomcat加插件好,这样能得到更好的可控性。
并且我不用Tomcat,用Redis,这个msm就用不上啦,不过我会按照个人思想实现session共享,呵呵,我的愚见!

 

tomcat架构

 

最后咱们的架构是这样的。在这样的解构下,咱们不管是修改成 二级目录 亦或是二级域名,咱们运维都只是要作很小的改动就能切换。配置和源码分离的结构,对咱们之后的扩展为分布式应用,仍是依然是单机的传统结构都是进能够攻退以守。
留有余地,惟一不足就是nginx的单点问题,不过就单机体系来讲已经够用了。

集群

上面不架构已是属于在单机上作了一个简单的集群了,要实现Tomcat。
要多台机器,只要修改上面Nginx的分发的Ip 就可,可是会话共享是一个很大的问题,可是,用基于IP分发的策略已经能解决绝大部分需求。
这里已经脱离了咱们单机应用的主题,之后有机会探讨。

参考文章:
http://www.cnblogs.com/tq03/p/3507658.html
http://www.itnose.net/detail/6658488.html
http://www.ttlsa.com/tomcat/config-multi-tomcat-instance/
http://www.cnblogs.com/_popc/p/4167516.html
http://www.itnose.net/detail/6485584.html
http://www.itnose.net/detail/6521677.html
http://www.itnose.net/detail/6448554.html
http://www.aikaiyuan.com/7907.html
http://blog.csdn.net/cclovett/article/details/26377269 (nginx)
http://www.roncoo.com/article/detail/125185

相关文章
相关标签/搜索