Динамическое расположение удаленного сервиса - Как внедрить с помощью Spring? - PullRequest
2 голосов
/ 16 марта 2012

В настоящее время я работаю над архитектурой распределенных сервисов для проекта на работе. По сути, мы управляем более 200 машин. На каждой из этих машин есть запущенная служба, которая позволяет нам взаимодействовать с машиной определенным образом.

В центре у меня есть контрольное приложение, которое должно общаться с этими 200 идентичными службами. Я надеялся использовать RMI через Spring Remoting, чтобы это произошло, что позволило мне @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>

Это второй бит конфигурации, который я пытаюсь сделать динамическим. Как видите, для создания этого прокси-сервера мне нужно знать URL-адрес сервиса во время создания компонента. URL службы может быть одним из 200+ вариантов, в зависимости от того, с какой машиной я хочу общаться. Служба, с которой я разговариваю, имеет тот же интерфейс, но я не буду знать, какая машина до времени выполнения, в зависимости от текущего контекста запроса.

1 Ответ

2 голосов
/ 17 марта 2012

Вы можете динамически создавать соединения с вашими серверами с помощью дополнительной службы и удалять «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. Порт и URL, или даже класс интерфейса могут быть настроены таким же образом.

У меня нет службы RMI для проверки этого, но она работала и с Гессианом. Я надеюсь, что это поможет вам.

...