CentOS 7 學習(三)配置Tomcat叢集

來源:互聯網
上載者:User

標籤:http   java   使用   os   io   檔案   資料   for   


所謂叢集,就是把多台伺服器集合起來,對外提供一個介面訪問,對使用者來說完全透明,常用的辦法就是前端放一個伺服器,將使用者請求分發到不同的伺服器,大致有以下幾種方案
1)採取DNS輪詢:將使用者的串連解析到不同的伺服器上,這會產生一個問題,如果一個伺服器宕掉,DNS無法及時更新,就會出現問題
2)反向 Proxy伺服器:將使用者的串連轉寄到不同的伺服器上,這有兩種方式,一個是修改HTTP頭,讓使用者的串連轉到固定的伺服器,以後不再和Proxy 伺服器互動,這會修改使用者瀏覽器裡的地址,可能會不怎麼友好;如果不修改地址,使用者總是通過Proxy 伺服器轉接,這個Proxy 伺服器可能會成為瓶頸。
3)MAC地址轉寄,所有的伺服器IP地址相同,通過裝置指向不同的機器。
對於代理問題,會產生Session共用的問題,有一種辦法就是針對特定使用者固定在一台伺服器上,這樣就不存在Session共用的問題了,這種方法最簡單,但是其演算法效率比較重要,需要自己選擇。還有就是將所有伺服器的Session共用,比如放在資料庫裡、共用目錄裡或者MemCached裡等,但是這些實現方式都有一定的問題,比如儲存的資料需要序列化、共用伺服器會成為系統薄弱點;再有就是將Session複製,讓所有的伺服器保持相同的Session資訊,這種情況如果需要伺服器過多,會嚴重的影響效能。
系統配置
CentOS 7,192.168.1.14,Apache 80, Nginx 808, Tomcat8 8081, Tomcat8 8082

可選的方案
1)Nginx:固定伺服器訪問,這個非常簡單,修改nginx.conf,採用ip_hash指令,如下
http {
.............
upstream tomcat_server_pool{
ip_hash;
server 192.168.1.14:8081 weight=4 max_fails=2 fail_timeout=30s;
server 192.168.1.14:8082 weight=4 max_fails=2 fail_timeout=30s;
}
server {
listen 808;
server_name localhost;

charset utf-8;

#access_log logs/host.access.log main;

if (-d $request_filename)
{
rewrite ^/(.*)([^/]) http://$host/$1$2/ permanent;
}
location / {
#root html;
index index.html index.htm index.do;

proxy_next_upstream http_502 http_504 error timeout invalid_header ;
proxy_pass http://tomcat_server_pool;
#proxy_set_header Host www.shiyq.com;
proxy_set_header X-Forwarded-For $remote_addr;
}

可以看出nginx將808連接埠轉寄到原生8081/8082,建立一個spring mvc項目,虛擬目錄為study,修改預設的檔案,如下
HomeController.java,增加以下內容
@RequestMapping(value = "/index.do", method = RequestMethod.GET)
public String home_do(Locale locale, Model model,HttpServletRequest request) {
logger.info("Welcome home! The client locale is {}.", locale);

Date date = new Date();
DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG);

String formattedDate = dateFormat.format(date);

String host_str = ", the host is " + request.getLocalAddr() + ":" + request.getLocalPort();
HttpSession session = request.getSession();

String check = request.getParameter("check");
if(check != null && !check.equals("")){
session.setAttribute("name", "石永強");
}

logger.info("the name in session is {}", (String)session.getAttribute("name"));
String test_Str = (String) session.getAttribute("host_str");


model.addAttribute("serverTime", formattedDate + ", the host is "+ host_str);

model.addAttribute("name",session.getAttribute("name"));

model.addAttribute("sessionId",session.getId());

return "home";
}
修改home.jsp,內容如下
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>
Hello world!
</h1>

<P> The time on the server is ${serverTime}. </P>
<P> The name in session is ${name}. </P>
<P> The session id is ${sessionId}. </P>
</body>
</html>
有時候會出現亂碼的問題,修改如下內容
在web.xml中加上如下
<filter>
<filter-name>Encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

上述配置適合解決method=post的問題,如果需要get方式支援中文,如form用get方式提交,或者點選連結支援中文,則需要修改 Tomcat根目錄的 conf/server.xml檔案中,找<Connector port="8080" />,在裡面加<Connector port="8080" uRIEncoding="utf-8" />
注意如果用於程式開發伺服器,需要找到正確的位置,如Eclipse的Servers下的設定檔。
但是在地址欄輸入中文,仍然無法支援,只能禁止這種方式。
在這種情況下,訪問http://192.168.1.14:808/study/index.do?check=1
輸出為
Hello world!
The time on the server is 2014年8月6日 上午11時39分48秒, the host is , the host is 192.168.1.14:8081.

The name in session is 石永強.

The session id is C318A769671490E6822C04752499380F.
重新整理之後,可以看到訪問的是固定的伺服器,這樣就能保證使用者Session不會出問題
2)使用MemCache
這需要Nginx的session外掛程式,還需要tomcat的memcache外掛程式,可是code.google.com訪問不了,雖然文檔很多,也實現不了,看以後吧。
只能採用Session複製的方式
3)tomcat 8配置cluster非常簡單,當然,這種叢集方式採取廣播的方式複製Session,當數量到了一定程度必然會引起廣播風暴,不適合大型系統
最簡單的設定方法:
A)將server.xml中<Cluster>標籤注釋去掉,預設如下
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
B)在需要複製Session的web-app中的web.xml增加一行:<distributable/>
C)關掉防火牆:service iptables stop,如果使用的是firewalld,使用命令service firewalld stop
設定Cluster需要注意的地方(官方文檔)
a)所有的session屬性必須實現java.io.Serializable
b)去掉server.xml中Cluster元素的注釋
c)如果要定製valves,確保要設定ReplicationValve
d)確保在web.xml中增加<distributable/>
e)如果使用了mod_jk,在Engine中要設定jvmRoute屬性為 workers.properties的worker名稱一致
f)確保所有的時間都相同,經過NTP伺服器的同步
g)確保你的負載平衡設定為會話粘連模式(sticky session mode)
在瀏覽器中訪問http://192.168.1.104:808/study/index.do,會發現在設定了ip_hash的情況下,根據頁面提示,會發現總是訪問一個伺服器,將這個tomcat關掉,再重新整理頁面,就會發現自動訪問另一個tomcat,而session資訊不變。
而且,如果去掉了ip_hash模式,nginx會自動按順序依次訪問系統,但其session ID不變。
如果要更好的測試可以,可以分別訪問http://192.168.1.14:8081/study/index.do和http://192.168.1.14:8082/study/index.do,會發現是一致的session ID,而且還可以訪問http://192.168.1.14:8081/study/index.do?check=1,這時候已經設定了session的屬性值,然後訪問http://192.168.1.14:8082/study/index.do,就可以知道確實發生了Session複製。
如果需要更複雜的定製效果,可以看一下文檔
對於防火牆的問題,可以增加如下規則
iptables -A INPUT -i eth0 -d 224.0.0.4 -j ACCEPT
vim /etc/sysconfig/iptables
增加以下內容:
-A INPUT -p udp -m state --state NEW -m udp --dport 45564 -j ACCEPT
啟動防火牆
service iptables save
service iptables start
3)Apache+mod_jk+tomcat方案
a)下載apache開發包
yum install httpd-*
b)下載mod_jk
wget http://mirrors.cnnic.cn/apache/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.40-src.tar.gz
tar xvf tomcat-connectors-1.2.40-src.tar.gz
cd tomcat-connectors-1.2.40-src.tar.gz
cd native
./configure --with-apxs=/bin/apxs
make
make install
c)配置Apache
因為httpd.conf包含conf.module.d目錄下檔案,在此目錄下建立00-add.conf,輸入以下內容

LoadModule jk_module modules/mod_jk.so #載入模組
JkWorkersFile conf/worker.properties #載入mod_jk設定檔

JkMount /* worker3 #將根目錄轉寄到worker3,worker3是一個負載平衡伺服器,包含兩台apache伺服器

<IfModule dir_module>
DirectoryIndex index.jsp index.do
</IfModule>
d)在conf目錄下建立workder.properties檔案,內容如下
worker.list = worker3
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009
worker.worker1.lbfactor=1
worker.worker1.connection_pool_timeout=600
worker.worker1.socket_keepalive=1
worker.worker1.socket_timeout=60

worker.worker2.type=ajp13
worker.worker2.host=localhost
worker.worker2.port=8010
worker.worker2.lbfactor=1
worker.worker2.connection_pool_timeout=600
worker.worker2.socket_keepalive=1
worker.worker2.socket_timeout=60

worker.worker3.type = lb
worker.worker3.balance_workers = worker1, worker2
可以看出worker1對應原生8009連接埠,即前面配置過的tomcat8-1,worker2對應原生8010連接埠,即之前配置過的tomcat8-2伺服器,worker3代表負載平衡伺服器,包括兩個成員worker1,worker2
e)配置tomcat
vim /work/tomcat8-1/conf/server.xml
修改如下內容,在Engine標籤增加jvmRoute="worker1"
<Engine name="Catalina" defaultHost="localhost" jvmRoute="worker1">
vim /work/tomcat8-2/conf/server.xml
修改如下內容,在Engine標籤增加jvmRoute="worker2"
<Engine name="Catalina" defaultHost="localhost" jvmRoute="worker2">
f)重啟Apache和tomcat,瀏覽器中輸入http://192.168.1.14/study/index.do,可以看到類似的內容
The time on the server is 2014年8月6日 下午05時21分04秒, the host is , the host is 192.168.1.14:80.

The name in session is .

The session id is AE132D73152E74C043ED64ED6F27707E.worker2.
這裡有一個有意思的事情,session id會增加一個i額尾碼,即worker1或者workder2,應該是jvmRoute的作用,但本質來說還是一個session
用mod_jk的一個問題是不知道訪問的是哪台機器,因為顯示的apache的地址連接埠,通過session可以知道到底是哪台機器。
之前我們配置過nginx的均衡,瀏覽器輸入http://192.168.1.14:808/study/index.do
會看到session id去掉尾碼確實是一樣的,而且運行http://192.168.1.14:808/study/index.do?check=1可以看到session資訊是共用的。

總體來說,用nginx配置負載平衡要容易的多,mod_jk要麻煩一些,tomcat的session複製也非常容易,只不過要記住配置防火牆,如果出現問題,要第一時間關掉防火牆,有可能就好了。

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.