集群發現機制 在Ignite中的集群號稱是無中心的,而且支持命令行啟動和嵌入應用啟動,所以按理說很簡單。而且集群有自動發現機制感覺對於懶人開發來說太好了,抱著試一試的心態測試一下吧。 在Apache Ignite中有三種自有的發現機制:組播、靜態IP、組播+靜態IP。下麵就這幾種來試一試吧。 測試方 ...
集群發現機制
在Ignite中的集群號稱是無中心的,而且支持命令行啟動和嵌入應用啟動,所以按理說很簡單。而且集群有自動發現機制感覺對於懶人開發來說太好了,抱著試一試的心態測試一下吧。
在Apache Ignite中有三種自有的發現機制:組播、靜態IP、組播+靜態IP。下麵就這幾種來試一試吧。
測試方法簡述
測試的方法主要是通過搭建2台tomcat伺服器,使用nginx來代理這2台tomcat,tomcat伺服器里有一個web應用,此應用內通過Apache Ignite webSession cluster來完成集群。具體的配置與方法可以參考《Apache Ignite高性能分散式網格框架-初探》。
集群發現機制測試-組播模式
按照Ignite的手冊組播是不需要做太多的配置的,預設即可,我在本機搭建兩個tomcat發現確實是可以實現自動發現的,啟動後確實完成用戶登錄,關閉其中一臺tomcat發現用戶登錄狀態還是保持了。
但是我把這種場景搬到伺服器上發現就不靈了,原因可能是區域網禁用了組播。組播這塊我也不是很瞭解就跳過了。
靜態ip發現的一些問題研究
節點都是服務端模式
為了達到集群的目的,於是還是使用靜態IP的方式吧,下麵是我的xml配置文件:
<!-- Provide configuration bean. -->
<bean id="cacheManager" class="org.apache.ignite.cache.spring.SpringCacheManager">
<property name="configuration">
<bean class="org.apache.ignite.configuration.IgniteConfiguration">
<!-- 客戶端模式設置,為true時開啟客戶端模式 -->
<property name="clientMode" value="false"/>
<property name="cacheConfiguration">
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="partitioned"/>
<property name="cacheMode" value="PARTITIONED"/>
<property name="backups" value="1"/>
</bean>
</property>
<property name="discoverySpi">
<bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
<property name="ipFinder">
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
<property name="multicastGroup" value="224.0.0.100"/>
<property name="addresses">
<list>
<value>192.168.36.116:47500..47509</value>
<value>192.168.49.204:47500..47509</value>
</list>
</property>
</bean>
</property>
</bean>
</property>
</bean>
</property>
</bean>
我是直接在spring中做的配置,其中啟動了一個緩存叫partitioned,用於存websession,而且使用了PARTITIONED模式,數據會分片存儲且備份,並且設定了備份數為1,也就是說每一個session都至少有一個備份。
另外我指定了一個發現器是TcpDiscoveryMulticastIpFinder,這個發現器可以指定組播地址和靜態地址,前面已經測試過了組播地址不生效,所以下麵就加了兩台tomcat的ip及埠範圍。
這樣配置後,發現Ignite的集群組建成功了,我隨便找了一個日誌:
2016-11-23 15:45:00,570 INFO [org.apache.ignite.internal.managers.discovery.GridDiscoveryManager] - Topology snapshot [ver=4, servers=2, clients=0, CPUs=8, heap=3.4GB]
這裡發現已經有2台server連接上了,其中可用8個CPU和3.4GB記憶體。此時客戶端通過nginx訪問OK了,說明這種集群是可以的。
節點中一個服務端一個客戶端
因為Ignite可以配置為客戶端模式,所以將其中192.168.49.204這台設置為客戶端模式,然後先啟動192.168.36.116這台tomcat,再啟動192.168.49.204這台。
查看192.168.46.116的日誌發現:
2016-11-23 15:52:54,454 INFO [org.apache.ignite.internal.managers.discovery.GridDiscoveryManager] - Topology snapshot [ver=8, servers=1, clients=1, CPUs=8, heap=3.4GB]
發現已經有變成了一臺server和一臺client,這說明集群也成功了。
然後訪問nginx的地址並登錄系統,正常。為了測試一下我們並了49.204這台client機,再訪問登錄的會話是保持的,這說明狀態已經保留。
下麵再啟動49.204,測試一下關閉server的情況,接著訪問系統會發現報錯了:
2016-11-23 15:59:38,819 ERROR [root] - Failed to update web session: null
class org.apache.ignite.IgniteException: Failed to wait for retry: class org.apache.ignite.lang.IgniteFutureTimeoutException: Timeout was reached before computation completed.
at org.apache.ignite.cache.websession.WebSessionFilter.handleCacheOperationException(WebSessionFilter.java:903)
at org.apache.ignite.cache.websession.WebSessionFilter.handleLoadSessionException(WebSessionFilter.java:596)
at org.apache.ignite.cache.websession.WebSessionFilter.doFilterV2(WebSessionFilter.java:522)
at org.apache.ignite.cache.websession.WebSessionFilter.doFilterDispatch(WebSessionFilter.java:406)
at org.apache.ignite.cache.websession.WebSessionFilter.doFilter(WebSessionFilter.java:382)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at com.hundsun.jresplus.web.servlet.SimpleOncePerRequestFilterChain$SimpleFilterChain.doFilter(SimpleOncePerRequestFilterChain.java:77)
at com.hundsun.jresplus.web.contain.ContainFilter.doFilter(ContainFilter.java:59)
at com.hundsun.jresplus.ui.contain.HornContainFilter.doFilter(HornContainFilter.java:46)
at com.hundsun.jresplus.web.servlet.SimpleOncePerRequestFilterChain$SimpleFilterChain.doFilter(SimpleOncePerRequestFilterChain.java:79)
at com.hundsun.jresplus.web.nosession.NoSessionFilter.doFilterInternal(NoSessionFilter.java:96)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
at com.hundsun.jresplus.web.servlet.SimpleOncePerRequestFilterChain$SimpleFilterChain.doFilter(SimpleOncePerRequestFilterChain.java:79)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
at com.hundsun.jresplus.web.servlet.SimpleOncePerRequestFilterChain$SimpleFilterChain.doFilter(SimpleOncePerRequestFilterChain.java:79)
at com.hundsun.jresplus.web.servlet.SimpleOncePerRequestFilterChain.doFilter(SimpleOncePerRequestFilterChain.java:49)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:343)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:260)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:505)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:957)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:620)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:722)
重新啟動36.116伺服器,發現訪問頁面不報錯了,但是登錄會話丟失。這說明客戶端模式的節點不保存數據。
測試一下靜態IP指定
在之前的測試中靜態IP是指定了全部的機器,那麼如果只指定一個IP會如何呢?對節點啟動順序是否有影響。下麵將ip保住192.168.36.116,另一個刪除掉:
<property name="addresses">
<list>
<value>192.168.36.116:47500..47509</value>
</list>
</property>
- 先啟動49.204——>系統登錄——>再啟動36.116
結果啟動49.204,發現訪問系統頁面失敗,返回的是nginx的報錯頁面,說明沒有代理到49.204上。查看日誌發現:
2016-11-23 16:07:56,932 WARN [org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi] - Failed to connect to any address from IP finder (will retry to join topology every 2 secs): [/192.168.36.116:47500, /192.168.36.116:47501, /192.168.36.116:47502, /192.168.36.116:47503, /192.168.36.116:47504, /192.168.36.116:47505, /192.168.36.116:47506, /192.168.36.116:47507, /192.168.36.116:47508, /192.168.36.116:47509]
說明這種設置了靜態Ip情況下如果發現指定的節點找不到則會卡住,導致tomcat也不往下走了。所以說這種情況不用再測試了直接over。
- 先啟動36.116-——>系統登錄——>再啟動49.204
這種模式沒問題,訪問nginx的服務地址可以訪問到兩台伺服器。所以必須有一個伺服器節點。而且啟動順序也必須是先啟動伺服器節點再啟動客戶端節點才行。
測試伺服器模式只配置靜態IP192.168.36.116
上面測試了一個靜態IP分服務端+客戶端的模式,如果兩台都是服務端呢?會不會有什麼影響,為了驗證,把49.204的模式改為服務端模式,然後配置作如下修改
<!-- 客戶端模式設置,為true時開啟客戶端模式 -->
<property name="clientMode" value="false"/>
<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder">
<property name="multicastGroup" value="224.0.0.100"/>
<property name="addresses">
<list>
<value>192.168.36.116:47500..47509</value>
</list>
</property>
</bean>
下麵步驟:
- 啟動49.204 ->正常,而面可以訪問
- 系統登錄 ->正常,登錄成功
- 啟動36.116 ->失敗,瀏覽系統發登錄狀態丟失
- 再系統登錄 ->失敗,無法登錄成功
- 關閉49.204 ->正常
- 再登錄系統 ->正常,可以登錄
- 啟動49.204 ->正常,登錄狀態保持了
這個過程發現如果發現器里只指定了靜態IP,但是此靜態IP所在的節點沒有啟動則無法保存數據。只有先啟動36.116後才能正常使用啊。
所以要使用靜態IP的話要在靜態IP列表裡寫入所有的節點IP才行
總結
初步試驗下來感覺Ignite的使用還是比較簡單的,只不過使用新事物總是會遇到一些問題,所以還是要多多瞭解,否則真要是用在生產環境可能有問題了再查就麻煩了。
接下來再多驗證一下集群和集群的數據複製功能,然後再測試一下雙節點的性能。