- 單臺(tái)Linux服務(wù)器中如何部署多個(gè)獨(dú)立應(yīng)用,即多個(gè)應(yīng)用不能run在一個(gè)jboss實(shí)例中?
換言之,這個(gè)問題也可以這樣描述:在單臺(tái)Linux服務(wù)器中服務(wù)啟動(dòng)多個(gè)Jboss實(shí)例?
默認(rèn)情況下,jboss啟動(dòng)時(shí)加載server/default/目錄下的配置,要實(shí)現(xiàn)多個(gè)實(shí)例的啟動(dòng),主要是解決端口沖突的問題,因?yàn)橐惶锥丝谥荒鼙灰粋€(gè)應(yīng)用占有;
一般來說,我們可以在Jboss啟動(dòng)時(shí)通過-Djboss.server.home設(shè)置當(dāng)前實(shí)例啟動(dòng)時(shí)加載不同的目錄來實(shí)現(xiàn);
比如Jboss主程序安裝在/usr/xx/jboss/,應(yīng)用放在/home/admin/app/;那此時(shí)就可以cp一份default目錄到當(dāng)前應(yīng)用app目錄下,通過-Djboss.server.home=/home/admin/app/default來啟動(dòng)該實(shí)例;
若直接在/usr/xx/jboss/server/下復(fù)制default目錄并改名為yy,則可以用更簡單的參數(shù)-c yy來啟動(dòng);
對(duì)于多應(yīng)用的情況,我們?nèi)匀灰鉀Q端口沖突的問題,有兩種方式:
其一,直接修改各應(yīng)用對(duì)應(yīng)的default目錄下的所有配置端口,主要涉及配置文件conf/jboss-service.xml、tomcat下的server.xml;該方法比較土,很容易出錯(cuò),因?yàn)槎丝诒姸啵灰幸豁?xiàng)端口沒有改,jboss就將無法正常啟動(dòng);若應(yīng)用較少,比如就只有2個(gè),那這種方式勉強(qiáng)可以用用;
其二,在jboss-service.xml中啟用jboss.system:service=ServiceBindingManager這個(gè)mbean服務(wù),設(shè)置ServerName、StoreURL屬性;將各套應(yīng)用對(duì)應(yīng)的端口全部配置在同一個(gè)文件中;推薦采用該方案,具體可參考:
- <mbean code="org.jboss.services.binding.ServiceBindingManager"
- name="jboss.system:service=ServiceBindingManager">
- <attribute name="ServerName">ports-01</attribute>
- <attribute name="StoreURL">${jboss.home.url}/docs/examples/binding-manager/sample-bindings.xml</attribute>
- <attribute name="StoreFactoryClassName">
- org.jboss.services.binding.XMLServicesStoreFactory
- </attribute>
- </mbean>
一般來說,上面的異常出現(xiàn)在4.2及其以后的版本中,比較詳細(xì)的異常如下:
- javax.management.MBeanRegistrationException: preRegister() failed: [ObjectName='jboss.remoting:service=NetworkRegistry', Class=org.jboss.remoting.network.NetworkRegistry (org.jboss.remoting.network.NetworkRegistry@16b6c55)]
- at org.jboss.mx.server.registry.BasicMBeanRegistry.invokePreRegister(BasicMBeanRegistry.java:713)
- at org.jboss.mx.server.registry.BasicMBeanRegistry.registerMBean(BasicMBeanRegistry.java:211)
- at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:585)
- at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
- ... 51 more
- Caused by: java.lang.RuntimeException: Exception creating identity: mall_dev4: mall_dev4
- at org.jboss.remoting.ident.Identity.get(Identity.java:211)
- at org.jboss.remoting.network.NetworkRegistry.preRegister(NetworkRegistry.java:268)
- at org.jboss.mx.server.AbstractMBeanInvoker.invokePreRegister(AbstractMBeanInvoker.java:966)
- at org.jboss.mx.modelmbean.ModelMBeanInvoker.invokePreRegister(ModelMBeanInvoker.java:489)
- at org.jboss.mx.server.AbstractMBeanInvoker.preRegister(AbstractMBeanInvoker.java:654)
- at org.jboss.mx.server.registry.BasicMBeanRegistry.invokePreRegister(BasicMBeanRegistry.java:697)
- ... 56 more
這主要是因?yàn)镴boss啟動(dòng)了一個(gè)jboss.remoting:service=NetworkRegistry的mbean服務(wù),啟動(dòng)時(shí)卻又無法根據(jù)當(dāng)前hostname找到IP!
解決方案為在/etc/hosts中綁定當(dāng)前服務(wù)器的主機(jī)名和IP,比如10.2.224.214 mall_dev4;
對(duì)于4.2系列之前的版本,如果沒有綁定主機(jī)名和IP,雖然會(huì)出現(xiàn)以下的異常,但并不一定會(huì)影響應(yīng)用的正常啟動(dòng);
- 11:32:12,427 WARN [ServiceController] Problem starting service jboss:service=invoker,type=http
- java.net.UnknownHostException: mall_dev4: mall_dev4
- at java.net.InetAddress.getLocalHost(InetAddress.java:1308)
- at org.jboss.invocation.http.server.HttpInvoker.checkInvokerURL(HttpInvoker.java:204)
- at org.jboss.invocation.http.server.HttpInvoker.startService(HttpInvoker.java:101)
- at org.jboss.system.ServiceMBeanSupport.jbossInternalStart(ServiceMBeanSupport.java:289)
- at org.jboss.system.ServiceMBeanSupport.jbossInternalLifecycle(ServiceMBeanSupport.java:245)
- at sun.reflect.GeneratedMethodAccessor2.invoke(Unknown Source)
- at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
- at java.lang.reflect.Method.invoke(Method.java:585)
- at org.jboss.mx.interceptor.ReflectedDispatcher.invoke(ReflectedDispatcher.java:155)
- at org.jboss.mx.server.Invocation.dispatch(Invocation.java:94)
- at org.jboss.mx.server.Invocation.invoke(Invocation.java:86)
- at org.jboss.mx.server.AbstractMBeanInvoker.invoke(AbstractMBeanInvoker.java:264)
- at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:659)
- at org.jboss.system.ServiceController$ServiceProxy.invoke(ServiceController.java:978)
- at $Proxy0.start(Unknown Source)
- at org.jboss.system.ServiceController.start(ServiceController.java:417)
熟悉Linux相關(guān)知識(shí)的筒靴都知道一個(gè)端口是綁定在某個(gè)地址上的,可以是一個(gè),也可以是多個(gè),一個(gè)端口在同一個(gè)地址上不能被兩個(gè)應(yīng)用占有;
出現(xiàn)這個(gè)問題一般是因?yàn)槟闶褂玫氖?.2系列及其之后的版本,因?yàn)閺倪@個(gè)系列開始,Jboss默認(rèn)綁定的端口由之前的0.0.0.0變成了127.0.0.1;前者表示綁定當(dāng)前服務(wù)器下所有地址,包括自身的IP、127.0.0.1;而后者只綁定了127.0.0.1,而沒有綁定本機(jī)IP,通過IP去訪問應(yīng)用自然也就無法成功了,因?yàn)樵L問的IP地址沒有開放對(duì)應(yīng)的端口;
對(duì)于默認(rèn)的這種情況,一般來說jboss是要和apache搭配使用的,apache暴露應(yīng)用外部訪問的端口,然后apache再監(jiān)聽本地(也就是127.0.0.1)的端口;
當(dāng)然這個(gè)默認(rèn)配置也是可以修改的,方式也比較多,比如:
方式1,啟動(dòng)腳本中通過參數(shù)-b, --host=<host or ip>指定地址,比如-b 0.0.0.0就表示綁定所有地址;
方式2,啟動(dòng)腳本中通過參數(shù)-Djboss.bind.address指定地址,比如-Djboss.bind.address=0.0.0.0;
方式3,直接修改需要對(duì)外暴露的端口綁定地址,比如tomcat/server.xml中的http端口綁定address信息;
對(duì)于jboss的關(guān)閉,shutdown命令允許好幾種方式的關(guān)閉,可以參考該命令的幫助:
- usage: shutdown [options] <operation>
- options:
- -h, --help Show this help message (default)
- -D<name>[=<value>] Set a system property
- -- Stop processing options
- -s, --server=<url> Specify the JNDI URL of the remote server
- -n, --serverName=<url> Specify the JMX name of the ServerImpl
- -a, --adapter=<name> Specify JNDI name of the MBeanServerConnection to use
- -u, --user=<name> Specify the username for authentication
- -p, --password=<name> Specify the password for authentication
- operations:
- -S, --shutdown Shutdown the server
- -e, --exit=<code> Force the VM to exit with a status code
- -H, --halt=<code> Force the VM to halt with a status code
若是基于JNDI URL的方式出現(xiàn)這種情況一般有三種可能:
其一,當(dāng)前應(yīng)用所使用的default目錄內(nèi)的內(nèi)容與當(dāng)前運(yùn)行jboss自身的default內(nèi)容不一致,比如當(dāng)前jboss版本為4.0.5,而啟動(dòng)時(shí)指定的default卻是從jboss 4.2.1中cp過來的;這種情況在搭建環(huán)境時(shí)經(jīng)常出現(xiàn),因?yàn)橐话阒苯訌牧硗庖慌_(tái)linux服務(wù)器中scp過來,但其實(shí)兩臺(tái)服務(wù)器自身安裝的jboss版本不一致;
其二,shutdown命令中指定的JNDI端口與實(shí)際應(yīng)用啟動(dòng)的JNDI端口不一致;
其三,/etc/hosts中對(duì)當(dāng)前主機(jī)名綁定的IP地址不正確,比如當(dāng)前服務(wù)器實(shí)際的IP地址為10.2.224.214,而hosts中綁定的卻是10.0.0.1;
總之,出現(xiàn)此類情況都是因?yàn)閖boss自身無法正確接收到正確的關(guān)閉命令所致,一般來說在jboss的server.log中會(huì)拋如下的異常信息:
- Exception in thread "main" javax.naming.CommunicationException [Root exception is java.rmi.ConnectException: Connection refused to host: 10.0.0.1; nested exception is:
- java.net.ConnectException: Connection timed out]
- at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:707)
- at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:572)
- at javax.naming.InitialContext.lookup(InitialContext.java:351)
- at org.jboss.Shutdown.main(Shutdown.java:202)
- Caused by: java.rmi.ConnectException: Connection refused to host: 10.0.0.1; nested exception is:
- java.net.ConnectException: Connection timed out
- at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:574)
- at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:185)
- at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:171)
- at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:94)
- at org.jnp.server.NamingServer_Stub.lookup(Unknown Source)
- at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:610)
- ... 3 more
其實(shí)這個(gè)問題和Jboss是否部署在Linux下沒有直接關(guān)系,可以在jboss啟動(dòng)時(shí)指定遠(yuǎn)程debug端口即可,比如:
- -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n
然后在eclipse中新建remote debug時(shí)指定對(duì)應(yīng)的端口即可;
Linux下Jboss啟動(dòng)、關(guān)閉、端口配置等常見問題FAQ
關(guān)于JBOSS端口被占用的問題