2012-03-16 43 views
2

我目前正在为一个项目工作分布式服务架构。实质上,我们正在管理200台以上的机器。这些机器中的每一台都有一个在其上运行的服务实例,使我们能够以特定方式与机器进行交互。动态远程服务位置 - 如何使用Spring注入?

在中心我有一个控制应用程序需要与这200个相同的服务交谈。我希望通过Spring Remoting使用RMI来实现这一点,允许我将我的远程服务@Autowire放入我的@Controller中,并将其视为具有异常传播的本地服务,并可能在未来通过挂钩传播事务/安全上下文。

这对于单个机器上的单个服务非常有用,我可以在我的Spring配置中对远程服务进行硬编码,但是我无法弄清楚的是如何动态选择哪种服务(又名哪台机器)我想在运行时进行交谈,并使该远程服务可用“Spring”方式。

我希望能够从数据库表中动态配置它,并使用相同的表信息进行服务查找,同时仍然利用依赖注入。

我想也许注入某种服务管理器,可以做某种服务查找,但希望别人已经设法解决这个(或类似的)问题优雅。

硬编码的,单个服务实例的一个例子是如下所示:

第一XML片段是在机器服务本身,告诉Spring来通过RMI

<!-- Expose DeviceService via RMI --> 
<bean class="org.springframework.remoting.rmi.RmiServiceExporter"> 
    <property name="serviceName" value="DeviceService" /> 
    <property name="service" ref="deviceService" /> 
    <property name="serviceInterface" 
     value="com.example.service.DeviceService" /> 
    <property name="registryPort" value="1199" /> 
</bean> 

第二XML将其暴露片段是在客户端(控制应用程序),它让我访问公开的服务

<!-- Proxy our remote DeviceService via RMI --> 
<bean id="remoteDeviceService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"> 
    <property name="serviceUrl" value="rmi://machineurl:1199/DeviceService"/> 
    <property name="serviceInterface" value="com.example.service.DeviceService"/> 
</bean> 

这是我试图使第二位的配置动态。如您所见,要创建此服务代理,我需要在创建bean时知道服务URL。服务URL可以是200多个变体中的1个,具体取决于我想要与哪个机器通话。我正在与之交谈的服务是相同的界面,但根据当前的请求上下文,直到运行时才会知道哪台机器。

+0

那么你的控制应用程序是客户端?硬编码版本是什么样的? – Stefan 2012-03-16 19:32:46

+0

我试图使它成为一个尽可能通用的问题,但在这种情况下,“控制”应用程序实际上是另一个服务层,它本身就是这些远程服务的客户端。我将添加一个硬编码的XML配置示例。 – 2012-03-16 20:08:48

回答

2

你可以创建你的服务器的连接动态地附加服务,并从客户端/控制研究的应用程序,即去掉“remoteDeviceService”:

public class RMIConnectionService { 

    public DeviceService connect(String serverUrl) { 
     RmiProxyFactoryBean factory = new RmiProxyFactoryBean(); 
     factory.setServiceInterface(DeviceService.class); 
     factory.setServiceUrl("rmi://" + serverUrl + ":1099/SERVICE_URL"); 
     factory.afterPropertiesSet(); 
     //... 
     return (DeviceService) factory.getObject(); 
    } 
} 

然后加入这项服务,你服务层:

<bean id="rmiService" class="...RMIConnectionService" > 
    //... 
</bean> 

在你的逻辑自动装配服务,并使用它像:

DeviceService server1 = rmiService.connect("127.0.0.1"); 

对于数据库配置添加您的DAO到这个服务,加载正确的URL。端口和网址,甚至接口类都可以这样配置。

我没有RMI服务来测试这个,但它也与Hessian一起工​​作。我希望这可以帮助你。

+0

这就是我对ServiceManager的想法所想到的,尽管我并不确定实现是什么样的。此外,我可能想要添加一些缓存,以便每个远程服务URL只有一个代理实例。您的实施看起来像是一个可行的选择。 – 2012-03-16 21:08:46

+0

使用此实现,由于**缓存的**旧端点不可访问,因此使用新端点对此方法的新调用会导致连接异常;它不会更新为使用新端点,即使我们使用* new *。 – 2016-08-25 13:32:05