使用Spring Boot 与Rabbitmq 实现rpc 调用
定义接口
public interface RemoteLoginInterface {
SecurityUserDetails remoteLoginUser(String username);
}
Client 端
- 配置 AmqpProxyFactoryBean 对象代理. 使用Spring Remote 做底层实现.
@Configuration
public class RemoteLoginClientConfig {
@Bean
public AmqpProxyFactoryBean remoteLoginClientService(CachingConnectionFactory cachingConnectionFactory) {
RabbitTemplate template = new RabbitTemplate(cachingConnectionFactory);
template.setReplyTimeout(20000);
AmqpProxyFactoryBean proxy = new AmqpProxyFactoryBean();
proxy.setAmqpTemplate(template);
proxy.setServiceInterface(RemoteLoginInterface.class);
proxy.setRoutingKey(UnderscoreUtil.underscoreName(RemoteLoginInterface.class.getSimpleName()));
return proxy;
}
}
@Slf4j
@Component
public class UserDetailsServiceImpl implements UserDetailsService {
@Resource
private RemoteLoginInterface remoteLoginInterface;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
SecurityUserDetails user = remoteLoginInterface.remoteLoginUser(username);
if (user == null) {
throw new UsernameNotFoundException("用户不存在");
}
return user;
}
}
Server 端
- 配置 AmqpInvokerServiceExporter .
- Server 端需要配置 queue 监听.
SimpleMessageListenerContainer
. rabbitmq rpc 使用的reply-to 队列完成
@Configuration
public class RemoteLoginServerConfig {
@Bean
public Queue remoteLoginQueue() {
return new Queue(UnderscoreUtil.underscoreName(RemoteLoginInterface.class.getSimpleName()));
}
@Bean
public SimpleMessageListenerContainer remoteLoginContainer(ConnectionFactory connectionFactory, Queue remoteLoginQueue, AmqpInvokerServiceExporter remoteLoginServiceExporter) {
SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
container.setQueues(remoteLoginQueue);
container.setMessageListener(remoteLoginServiceExporter);
container.setConcurrency("5-10");
container.setPrefetchCount(10);
return container;
}
@Bean
public AmqpInvokerServiceExporter remoteLoginServiceExporter(AmqpTemplate amqpTemplate, RemoteLoginInterface remoteLoginInterface) {
AmqpInvokerServiceExporter exporter = new AmqpInvokerServiceExporter();
exporter.setAmqpTemplate(amqpTemplate);
exporter.setService(remoteLoginInterface);
exporter.setServiceInterface(RemoteLoginInterface.class);
return exporter;
}
}
@Slf4j
@Component
public class RemoteLoginServer implements RemoteLoginInterface {
@Resource
private UserService userService;
@Override
public SecurityUserDetails remoteLoginUser(String username) {
SecurityUserDetails userDetails = userService.findByUsernameSec(username);
return userDetails;
}
}
注意
- 超时, 默认调用超时为5秒. 如果需要自定义在RabbitmqTemplate 上设置 replyTimeout.
- 如果没有reply queue 默认为
amq.rabbitmq.reply-to
- 参数与返回值都需要实现 Serializable 方法.序列化支持.
- 此调用只用于简单的rpc, 实际生产的话还有一段距离.
参考 SpringAmqp