为spring远程服务增加自动发现和群集功能
摘要
本文讨论了自动化远程服务发现如何简化复杂的多层企业级应用的开发和布署。作者通过布署在jboss环境中的基于spring的应用演示了这人过程。本文假设读者已有一些spring框架的知识。
版权声明:任何获得matrix授权的网站,转载时请务必保留以下作者信息和链接
作者:mikhail garber;xmatrix(作者的blog:http://blog.matrix.org.cn/page/xmatrix)
原文:javaworld.com/javaworld/jw-10-2005/jw-1031-spring.html
" target="_new">http://www.javaworld.com/javaworld/jw-10-2005/jw-1031-spring.html
译文:http://www.matrix.org.cn/resource/article/44/44200_spring+cluster.html
关键字:spring;cluster;remoting
当企业级计算进入新的soa世界时,在寻找描述/发布/和发现服务的方面中开始变得越来越重要。基于网络服务的方案不提供自动服务发现而且通常都太繁杂了。现在新的轻量级的开发框架提供了新的轻量级的服务发布方案。
在过去几年中,spring框架已经成为开发简单、灵活而且容易配置的j2ee应用的事实标准。spring的核心是ioc法则。根据ioc,应用必须以一个简单javabean的集合来开发,然后用一个轻量级的ioc容器来绑定他们并设置相关的依赖关系。
在spring中,容器通过一系列bean定义也配置,典型的是用xml文件方式:
<bean id="myservicebean" class="mypackage.myserviceimpl">
<property name="otherservice" ref="otherservicebean"/>
</bean>
myserviceinterface service = (myserviceinterface)context.getbean("myservicebean");
service.dosomething();
<bean name="/myremoteservice" class="org.springframework.remoting.httpinvoker.httpinvokerserviceexporter">
<property name="service" ref="myservicebean"/>
<property name="serviceinterface" value="mypackage.myserviceinterface"/>
</bean>
<bean id="myservicebean"
class="org.springframework.remoting.httpinvoker.httpinvokerproxyfactorybean">
<property name="serviceurl"
value="http://somehost:8080/webapp-context/some-mapping-for-spring-servlet/myremoteservice" />
<property name="serviceinterface"
value="mypackage.myserviceinterface" />
</bean>
<bean name="/testservice" class="app.service.autodiscoveredserviceexporter">
<property name="service" ref="testservice"/>
<property name="serviceinterface" value="app.service.testserviceinterface"/>
</bean>
<bean id="customtreecachembean" class="org.springframework.jmx.access.mbeanproxyfactorybean">
<property name="objectname">
<value>jboss.cache:service=customtreecache</value>
</property>
<property name="proxyinterface">
<value>org.jboss.cache.treecachembean</value>
</property>
</bean>
public void put(string path, object key, object value) throws exception;
public object get(string path, object key) throws exception;
<bean id="cacheservice" class="app.service.jbosscacheserviceimpl">
<property name="cachembean" ref="customtreecachembean"/>
</bean>
<bean id="servicepublisher" class="app.service.servicepublisher">
<property name="cache" ref="cacheservice"/>
</bean>
private void contextrefreshed() throws exception {
logger.info("context refreshed");
string[] names = context
.getbeannamesfortype(autodiscoveredserviceexporter.class);
logger.info("exporting services:" + names.length);
for (int i = 0; i < names.length; i++) {
string serviceurl = makeurl(names[i]);
try {
set services = (set) cache.get(service_prefix + names[i],
service_key);
if (services == null)
services = new hashset();
services.add(serviceurl);
cache.put(service_prefix + names[i], service_key, services);
logger.info("added:" + serviceurl);
} catch (exception ex) {
logger.error("exception adding service:", ex);
}
} <bean id="localcacheservice" class="app.auto.localjbosscacheserviceimpl">
</bean>
public localjbosscacheserviceimpl() throws exception {
super();
cache = new treecache();
propertyconfigurator config = new propertyconfigurator();
config.configure(cache, "app/context/custom-cache-service.xml");
}
<bean id="testservice"
class="app.auto.autodiscoveredservice">
<property name="serviceinterface"
value="app.service.testserviceinterface" />
<property name="cache" ref="localcacheservice"/>
</bean>
private list getserviceurls() throws exception {
set services = (set) cache.get(servicepublisher.service_prefix
+ beanname, servicepublisher.service_key);
if (services == null)
return null;
arraylist results = new arraylist(services);
collections.shuffle(results);
logger.info("shuffled:" + results);
return results;
} public object invoke(methodinvocation arg0) throws throwable {
list urls = getserviceurls();
if (urls != null)
for (iterator allurls = urls.iterator(); allurls.hasnext();) {
string serviceurl = null;
try {
serviceurl = (string) allurls.next();
super.setserviceurl(serviceurl);
logger.info("going to:" + serviceurl);
return super.invoke(arg0);
} catch (throwable problem) {
if (problem instanceof ioexception
problem instanceof remoteaccessexception) {
logger.warn("got error accessing:"
+ super.getserviceurl(), problem);
removefailedservice(serviceurl);
} else {
throw problem;
}
}
}
throw new illegalstateexception("no services configured for name:"
+ beanname);
} private void removefailedservice(string url) {
try {
logger.info("removing failed service:" + url);
set services = (set) cache.get(servicepublisher.service_prefix
+ beanname, servicepublisher.service_key);
if (services != null) {
services.remove(url);
cache.put(servicepublisher.service_prefix + beanname, servicepublisher.service_key,
services);
logger.info("removed failed service at:" + url);
}
} catch (exception e) {
logger.warn("failed to remove failed service:" + url, e);
}
} Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器