`
dwj147258
  • 浏览: 194020 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

spring集成rabbitmq实现rpc

阅读更多

 

public Object convertSendAndReceive(final String routingKey, final Object message) throws AmqpException {
		return this.convertSendAndReceive(this.exchange, routingKey, message, null);
	}

 一

 

 spring整合Rabbit MQ提供了Reply来实现RPC,AMQP协议定义了14中消息的属性,其中两项,一项是Replyto,表示返回消息的队列,一个是correlationId 用来表示发送消息和返回消息的标志,来区分是否是一个调用

下面一步步来实现RPC

首先贴出spring配置文件代码

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:rabbit="http://www.springframework.org/schema/rabbit"
	xmlns:prpc="http://www.pinnettech.com/schema/rpc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-4.0.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
		http://www.pinnettech.com/schema/rpc
		http://www.pinnettech.com/schema/springtag.xsd
		http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">
		<context:component-scan  
            base-package="com.temp.rabbit">  
   		</context:component-scan>
   		
   		<!-- rabbit消息发送方 -->
   		<!-- 连接服务配置 如果MQ服务器在远程服务器上,请新建用户用新建的用户名密码  guest默认不允许远程登录--> 
   		<rabbit:connection-factory id="rabbitConnectionFactory" host="localhost" username="dengwei" password="dengwei"
   			port="5672" virtual-host="/" channel-cache-size="5"/>
   		<rabbit:admin connection-factory="rabbitConnectionFactory"/>
   		<!-- 发送消息可以带*,绑定关系需全单词 -->
   		<rabbit:direct-exchange name="rpc.bao.direct.goods" durable="true" auto-delete="false">
   			<rabbit:bindings>
   				<rabbit:binding queue="rpc.bao.goods" key="dengwei.goods"/>
   			</rabbit:bindings>
   		</rabbit:direct-exchange>
   		
   		<!-- durable是否持久化  exclusive:是否排外的-->
   		<rabbit:queue durable="true" auto-delete="false" exclusive="false" name="rpc.bao.goods"/>
   		
   		<!-- 消息转换器 -->
   		<bean id="byteMessageConverter" class="com.temp.rabbit.BytesMessageConverter"/>
   		<!-- 发送消息模板 -->
   		<rabbit:template id="amqTemplate" exchange="rpc.bao.direct.goods" 
   			connection-factory="rabbitConnectionFactory" message-converter="byteMessageConverter" />
   		<!-- 消息发送方 end -->
   		
   		
   		<!-- 消息接受方处理器 -->
   		<bean id="msgHandler" class="com.temp.rabbit.receive.MessageHandler"/>
   		<!-- 消息消费者 -->
   		<bean id="msgLisenerAdapter" class="org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter">
   			<constructor-arg name="delegate" ref="msgHandler"/>
   			<constructor-arg name="messageConverter" ref="byteMessageConverter"/>
   		</bean>
		<!-- 消费者容器 -->   		
   		<rabbit:listener-container connection-factory="rabbitConnectionFactory" acknowledge="auto">
   		
   			<rabbit:listener queues="rpc.bao.goods" ref="msgLisenerAdapter"/>
   		</rabbit:listener-container>
   		
   		<!-- 消息接收方 end -->
   		<!--  RPC 配置 -->
   		<!-- 消息服务提供接口实现 -->
   		<bean id="service1" class="com.temp.rabbit.bean.TempServiceImp"/>
   		<!-- 代理类 -->
   		<bean id="service1Proxy" class="com.temp.rabbit.receive.proxy.ServiceProxy">
   			<property name="t" ref="service1"></property>
   		</bean>
   		<!-- 代理对象 -->
   		<bean id="proxyService" factory-bean="service1Proxy" factory-method="getProxy"/>
   		
</beans>

 其中消息转换器类:

 

 

package com.temp.rabbit;

import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.support.converter.AbstractJsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConversionException;
import org.springframework.util.SerializationUtils;

public class BytesMessageConverter extends AbstractJsonMessageConverter{

	@Override
	protected Message createMessage(Object msg, MessageProperties msgPro) {
		byte[] data = SerializationUtils.serialize(msg);
		msgPro.setContentLength(data.length);
		System.out.println("create message "+msg.getClass());
		return new Message(data , msgPro);
	}

	@Override
	public Object fromMessage(Message msg) throws MessageConversionException {
		byte[] data = msg.getBody() ;
		Object result = SerializationUtils.deserialize(data);
		System.out.println("create obj "+result.getClass());
		return result;
	}

}

 消费者处理handler

 

 

package com.temp.rabbit.receive;

import java.lang.reflect.Method;

import com.temp.rabbit.bean.RpcRequest;
import com.temp.rabbit.bean.RpcResponse;
import com.temp.rabbit.bean.TempServiceImp;

public class MessageHandler {

    //没有设置默认的处理方法的时候,方法名是handleMessage
    public RpcResponse handleMessage(RpcRequest message){
    	Class<?> clazz = message.getClassName() ;
    	RpcResponse response = new RpcResponse();
    	Method method;
		try {
			method = clazz.getMethod(message.getMethodName(), message.getParamType());
			Object result = method.invoke(new TempServiceImp(), message.getParams());
			response.setResult(result);
		} catch (Exception e) {
			e.printStackTrace();
		}
        return response ;
    }
}

 服务提供:

 

 

package com.temp.rabbit.bean;

public class TempServiceImp implements TempService {

	public String sayHello(){
		return "TempServiceImp hello ... " ;
	}
	
}

 代理类:

 

 

package com.temp.rabbit.receive.proxy;

import java.io.Serializable;
import java.lang.reflect.Method;

import org.springframework.beans.factory.annotation.Autowired;

import com.temp.rabbit.bean.RpcRequest;
import com.temp.rabbit.bean.RpcResponse;
import com.temp.rabbit.send.SendRabbitMsgImp;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class ServiceProxy<T> implements MethodInterceptor{

	private Enhancer enhancer = new Enhancer();
	
	private T t ;
	
	public void setT(T t){
		this.t = t ;
	}
	@Autowired
	private SendRabbitMsgImp rabbitMsg ;
	
	public Object getProxy(){
		enhancer.setSuperclass(t.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
	}
	
	
	@Override
	public Object intercept(Object obj, Method method, Object[] param, MethodProxy proxy) throws Throwable {
		RpcRequest request = new RpcRequest();
		request.setMethodName(method.getName());
		request.setClassName(t.getClass());
		Class<?>[] paramType = new Class<?>[param.length];
		Serializable[] para = new Serializable[param.length];
		for(int i = 0 ; i < param.length ; i ++){
			paramType[i] = param[i].getClass();
			para[i] = (Serializable)param[i];
		}
		request.setParams(para);
		request.setParamType(paramType);
		RpcResponse result = (RpcResponse)rabbitMsg.sendAdcReceive("dengwei.goods", request) ; 
		return result.getResult();
	}

}

 主程序

 

 

package com.temp;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.temp.rabbit.bean.TempService;

public class Main {

	public static void main(String[] args) {
		ApplicationContext app = new ClassPathXmlApplicationContext("classpath:spring.xml");  
		TempService proxy = (TempService)app.getBean("proxyService");
		System.out.println("main result " + proxy.sayHello()) ;
	}
	
} 

 

消息发送实现:

 

package com.temp.rabbit.send;

import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("sendMsg")
public class SendRabbitMsgImp implements SendRabbitMsg{

	@Autowired
	private RabbitTemplate template ;
	
	@Override
	public void sendData2Queue(String queueKey, Object msg) {
		try {
			template.convertAndSend(queueKey, msg);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("send data 2 msg erro ");
		}
		System.out.println("消息已发送");
	}
	
	@Override
	public Object sendAdcReceive(String queueKey , Object msg){
		try {
			return template.convertSendAndReceive(queueKey, msg);
		} catch (Exception e) {
			e.printStackTrace();
			System.out.println("send data 2 msg erro ");
		}
		System.out.println("消息已发送");
		return null ; 
	}
}

 

 

这里面的RpcRequest和RpcResponse就不贴代码了

这里讲一下原理实现,我们可以跟着源码看一下

首先调用的是RabbitTemplate的

 

public Object convertSendAndReceive(final String routingKey, final Object message) throws AmqpException {
		return this.convertSendAndReceive(this.exchange, routingKey, message, null);
	}

 然后一路走下去

@Override
	public Object convertSendAndReceive(final String exchange, final String routingKey, final Object message,
			final MessagePostProcessor messagePostProcessor) throws AmqpException {
		Message requestMessage = convertMessageIfNecessary(message);
		if (messagePostProcessor != null) {
			requestMessage = messagePostProcessor.postProcessMessage(requestMessage);
		}
		Message replyMessage = this.doSendAndReceive(exchange, routingKey, requestMessage);
		if (replyMessage == null) {
			return null;
		}
		return this.getRequiredMessageConverter().fromMessage(replyMessage);
	}

protected Message doSendAndReceive(final String exchange, final String routingKey, final Message message) {
		if (this.replyQueue == null) {
			return doSendAndReceiveWithTemporary(exchange, routingKey, message);
		}
		else {
			return doSendAndReceiveWithFixed(exchange, routingKey, message);
		}
	}

 到这里我们会看到,有一个分支如果replyqueue不为空则是走另外的一个方法,因为之前没有设置replyqueue所以,这里会

 

走第一步方法,也就是doSendAndReceiveWithTemporary

来看一下这个方法源码

 

protected Message doSendAndReceiveWithTemporary(final String exchange, final String routingKey, final Message message) {
		return this.execute(new ChannelCallback<Message>() {

			@Override
			public Message doInRabbit(Channel channel) throws Exception {
				final ArrayBlockingQueue<Message> replyHandoff = new ArrayBlockingQueue<Message>(1);

				Assert.isNull(message.getMessageProperties().getReplyTo(),
						"Send-and-receive methods can only be used if the Message does not already have a replyTo property.");
				DeclareOk queueDeclaration = channel.queueDeclare();
				String replyTo = queueDeclaration.getQueue();
				message.getMessageProperties().setReplyTo(replyTo);

				String consumerTag = UUID.randomUUID().toString();
				DefaultConsumer consumer = new DefaultConsumer(channel) {

					@Override
					public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties,
											   byte[] body) throws IOException {
						MessageProperties messageProperties = messagePropertiesConverter.toMessageProperties(
								properties, envelope, encoding);
						Message reply = new Message(body, messageProperties);
						if (logger.isTraceEnabled()) {
							logger.trace("Message received " + reply);
						}
						try {
							replyHandoff.put(reply);
						}
						catch (InterruptedException e) {
							Thread.currentThread().interrupt();
						}
					}
				};
				channel.basicConsume(replyTo, true, consumerTag, true, true, null, consumer);
				doSend(channel, exchange, routingKey, message, null);
				Message reply = (replyTimeout < 0) ? replyHandoff.take() : replyHandoff.poll(replyTimeout,
						TimeUnit.MILLISECONDS);
				channel.basicCancel(consumerTag);
				return reply;
			}
		});
	}

 这里流程就是申明一个大小为1的临时队列,然后发送消息,然后监听返回的消息,放到临时队列,然后取出返回消息。

 

那么因为每次都会创建临时队列,所以对性能是个考验那么有第二种方式,在rabbitmq中申明一个返回队列,用来存放该服务的返回消息。

那么需要在spring配置文件中配置一个reply队列

<rabbit:queue durable="true" auto-delete="false" exclusive="false" name="reply"/>

然后在消息监听容器中再配置一个发送消息的模板template为消费者

 

<!-- 消费者容器 -->   		
   		<rabbit:listener-container connection-factory="rabbitConnectionFactory" acknowledge="auto">
   			<rabbit:listener queues="reply" ref="amqTemplate"/>
   			<rabbit:listener queues="rpc.bao.goods" ref="msgLisenerAdapter"/>
   		</rabbit:listener-container>

 

 

最后再发送消息的实现中即SendRabbitMsgImp类中注入队列

 

 

@Autowired
	@Qualifier("reply")
	private Queue reply ;

 

 

然后设置template的replyqueue为reply     ;template.setReplyQueue(reply);

这个设置代码可以再初始化方法中,也可以再发送消息之前,其实最好的实在spring中设置

那么该说原理了,我们可以看最开始发送消息的第二个方法

protected Message doSendAndReceive(final String exchange, final String routingKey, final Message message) {
		if (this.replyQueue == null) {
			return doSendAndReceiveWithTemporary(exchange, routingKey, message);
		}
		else {
			return doSendAndReceiveWithFixed(exchange, routingKey, message);
		}
	}

 

protected Message doSendAndReceiveWithFixed(final String exchange, final String routingKey, final Message message) {
		return this.execute(new ChannelCallback<Message>() {

			@Override
			public Message doInRabbit(Channel channel) throws Exception {
				final PendingReply pendingReply = new PendingReply();
				String messageTag = UUID.randomUUID().toString();
				RabbitTemplate.this.replyHolder.put(messageTag, pendingReply);
				// Save any existing replyTo and correlation data
				String savedReplyTo = message.getMessageProperties().getReplyTo();
				pendingReply.setSavedReplyTo(savedReplyTo);
				if (StringUtils.hasLength(savedReplyTo) && logger.isDebugEnabled()) {
					logger.debug("Replacing replyTo header:" + savedReplyTo
							+ " in favor of template's configured reply-queue:"
							+ RabbitTemplate.this.replyQueue.getName());
				}
				message.getMessageProperties().setReplyTo(RabbitTemplate.this.replyQueue.getName());
				String savedCorrelation = null;
				if (RabbitTemplate.this.correlationKey == null) { // using standard correlationId property
					byte[] correlationId = message.getMessageProperties().getCorrelationId();
					if (correlationId != null) {
						savedCorrelation = new String(correlationId,
								RabbitTemplate.this.encoding);
					}
				}
				else {
					savedCorrelation = (String) message.getMessageProperties()
							.getHeaders().get(RabbitTemplate.this.correlationKey);
				}
				pendingReply.setSavedCorrelation(savedCorrelation);
				if (RabbitTemplate.this.correlationKey == null) { // using standard correlationId property
					message.getMessageProperties().setCorrelationId(messageTag
							.getBytes(RabbitTemplate.this.encoding));
				}
				else {
					message.getMessageProperties().setHeader(
							RabbitTemplate.this.correlationKey, messageTag);
				}

				if (logger.isDebugEnabled()) {
					logger.debug("Sending message with tag " + messageTag);
				}
				doSend(channel, exchange, routingKey, message, null);
				LinkedBlockingQueue<Message> replyHandoff = pendingReply.getQueue();
				Message reply = (replyTimeout < 0) ? replyHandoff.take() : replyHandoff.poll(replyTimeout,
						TimeUnit.MILLISECONDS);
				RabbitTemplate.this.replyHolder.remove(messageTag);
				return reply;
			}
		});
	}

 这个方法并没有申请临时队列,发送消息后直接再pendingReply中的队列中取,那么怎么放到pendingReply的队列中区的呢,可以看到,RabbitTemplate是实现了MessageLIstener,那么看他实现的onMessage方法

public void onMessage(Message message) {
		try {
			String messageTag;
			if (this.correlationKey == null) { // using standard correlationId property
				messageTag = new String(message.getMessageProperties().getCorrelationId(), this.encoding);
			}
			else {
				messageTag = (String) message.getMessageProperties()
						.getHeaders().get(this.correlationKey);
			}
			if (messageTag == null) {
				logger.error("No correlation header in reply");
				return;
			}

			PendingReply pendingReply = this.replyHolder.get(messageTag);
			if (pendingReply == null) {
				if (logger.isWarnEnabled()) {
					logger.warn("Reply received after timeout for " + messageTag);
				}
			}
			else {
				// Restore the inbound correlation data
				String savedCorrelation = pendingReply.getSavedCorrelation();
				if (this.correlationKey == null) {
					if (savedCorrelation == null) {
						message.getMessageProperties().setCorrelationId(null);
					}
					else {
						message.getMessageProperties().setCorrelationId(
								savedCorrelation.getBytes(this.encoding));
					}
				}
				else {
					if (savedCorrelation != null) {
						message.getMessageProperties().setHeader(this.correlationKey,
							savedCorrelation);
					}
					else {
						message.getMessageProperties().getHeaders().remove(this.correlationKey);
					}
				}
				// Restore any inbound replyTo
				String savedReplyTo = pendingReply.getSavedReplyTo();
				message.getMessageProperties().setReplyTo(savedReplyTo);
				LinkedBlockingQueue<Message> queue = pendingReply.getQueue();
				queue.add(message);
				if (logger.isDebugEnabled()) {
					logger.debug("Reply received for " + messageTag);
					if (savedReplyTo != null) {
						logger.debug("Restored replyTo to " + savedReplyTo);
					}
				}
			}
		}
		catch (UnsupportedEncodingException e) {
			throw new AmqpIllegalStateException("Invalid Character Set:" + this.encoding, e);
		}
	}

 这里就明白了,根据唯一id也就是前面说的correlationId找到消息的pendingReply,然后将返回的消息放到pendingReply的队列中,这样就实现了RPC的调用,下面附上工程代码

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    spring-rabbitmq-demo

    通过这样的集成,我们可以构建出高可用和可扩展的应用,利用RabbitMQ实现异步任务处理,提高系统的并发性能,并通过RPC实现跨服务间的通信。这不仅有助于优化系统资源的利用,还能降低服务之间的耦合度,提升整体...

    基于spring boot,集成了RPC、缓存、消息队列、分库分表、注册-spring-boot-bulking.zip

    在这个基于Spring Boot的项目中,我们看到了一系列关键的技术集成,包括RPC、缓存、消息队列、分库分表和注册中心。现在,让我们逐一深入这些技术领域,了解它们在实际项目中的作用和实现方式。 1. **RPC(Remote ...

    rabbitmq学习11:基于rabbitmq和spring-amqp的远程接口调用

    在本主题"rabbitmq学习11:基于rabbitmq和spring-amqp的远程接口调用"中,我们将深入探讨如何使用RabbitMQ作为消息中间件,结合Spring-AMQP库实现RPC模式。 RabbitMQ是一个开源的消息代理和队列服务器,它基于AMQP...

    SpringBoot+Zookeeper+Dubbo+rabbitMQ实现分布式高并发秒杀系统.zip

    【标题】"SpringBoot+Zookeeper+Dubbo+rabbitMQ实现分布式高并发秒杀系统"是一个集成多种技术的项目,旨在构建一个能够处理大规模并发请求的秒杀系统。这个系统利用了SpringBoot作为基础框架,提供了简洁的配置和...

    Spring Cloud Sleuth+RabbitMQ+Zipkin实现分布式链路追踪Demo程序

    总结来说,Spring Cloud Sleuth+RabbitMQ+Zipkin的结合提供了一套强大的解决方案,帮助我们在微服务环境中实现分布式链路追踪。通过这个Demo程序,我们可以学习如何配置和使用这些工具,以便更好地理解和调试我们的...

    RabbitMQ CookBook

    10. **集成实践**:展示RabbitMQ与其他技术(如Spring、Docker、Kubernetes等)的集成,以及在实际项目中的应用案例。 通过《RabbitMQ CookBook》,读者不仅可以学习到RabbitMQ的核心原理,还能掌握如何在实际项目...

    rabbitmq实战-rabbitmq-action.zip

    3.1 Spring整合:使用Spring框架集成RabbitMQ,包括配置、生产者和消费者组件的创建,以及消息模板的使用。 3.2 消息确认:消费者确认机制,确保消息被正确处理,防止消息丢失。 3.3 工作队列:通过多消费者并行处理...

    基于Spring Boot的分布式秒杀系统.zip

    本项目是一个基于Spring Boot的分布式秒杀系统,集成了多种技术和中间件,旨在提供高效、可靠的秒杀服务。系统包含多个模块,分别负责订单管理、商品管理、消息队列处理、通用功能和API接口等。 技术栈 前端...

    Lnk-RPC使用文档1

    如API(定义接口和公共工具)、Cluster(负载均衡策略实现)、Core(聚合功能实现RPC核心)、Demo(示例)、Flow(流量控制)、Lookup(服务注册发现)、Port(端口配置和分配)、Protocol(序列化协议)、Remoting...

    RabbitMQ工作模型及与Java 编程1

    在Java编程中,我们可以使用Spring框架集成RabbitMQ。Spring提供了`spring-amqp`模块,简化了与RabbitMQ的交互。基本步骤包括配置RabbitMQ连接,创建消息模板(`RabbitTemplate`),定义消息队列,以及设置生产者和...

    rabbitmq面试题.pdf

    如何在Spring Boot应用中集成RabbitMQ?** - 利用Spring框架提供的`spring-rabbit`模块进行集成。 - 配置连接工厂、交换器、队列等组件,并注入到应用程序中。 **18. RabbitMQ与Kafka比较,优缺点分别是什么?** ...

    dubbo+rabbitmq+springMvc+maven简单demo

    在本项目中,RabbitMQ取代了原本的ActiveMQ,作为消息中间件,实现服务间的异步通信,提高系统的响应速度和并发处理能力。 3. **SpringMvc**: SpringMvc是Spring框架的一部分,主要用于构建Web应用的后端控制器。...

    基于springboot的两个项目之间的远程调用

    - **RabbitMQ**:Spring Boot可以通过集成RabbitMQ实现消息队列的远程调用,适用于异步处理和解耦。 - **RESTful API**:基于HTTP协议,Spring Boot提供Spring MVC和WebFlux来创建RESTful服务,简单易用且跨平台。...

    springCloud

    一 服务启动 此项目集成了:Feign,Spring Cloud Bus,hystrix,swagger-ui,zuul-filter,配置中心功能 1)安装rabbitMQ 2)启动cloud—eureka :此时可访问 localhost:8761 3)启动 cloud-config 此处为配置中心 ...

    springcloud面试准备,面经

    同步通信可以通过 Dubbo 通过 RPC 远程过程调用、Spring Cloud 通过 REST 接口json 调用等实现。异步通信可以通过消息队列,如 RabbitMq、ActiveM、Kafka 等消息队列实现。 五、什么是服务熔断?什么是服务降级? ...

    rabbitmq:rabbitmq演示

    1. **Spring AMQP**:Spring提供了Spring AMQP模块,简化了RabbitMQ的集成。它包括RabbitTemplate和AmqpAdmin等工具类,用于发送和管理消息。 2. **配置**:在Spring Boot应用中,可以通过`application.yml`或`...

    基于SpingCloud、dubbo、nacos、zipkin、rabbitmq的微服务框架

    本文将详细探讨如何利用Spring Cloud、Dubbo、Nacos、Zipkin和RabbitMQ这些技术栈来搭建一个强大的微服务框架。 **Spring Cloud** Spring Cloud是基于Spring Boot的一个框架集合,它提供了开发分布式系统所需的...

    Spring Cloud 中文文档 参考手册 中文版2018

    Spring Cloud支持与多种编程语言的微服务实现集成,这包括使用RxJava与Spring MVC。同时,它也支持Sidecar模式,允许非JVM语言编写的微服务与Spring Cloud基础设施集成。 总的来说,Spring Cloud Dalston文档涉及了...

    基于java的springboot和dubbo、netty的集成模板

    Netty服务器可以与Spring Boot应用通过消息队列(如RabbitMQ)或直接调用Dubbo服务进行通信。 6. **测试与优化**:通过单元测试和集成测试确保各个组件协同工作。优化性能,如调整Dubbo的超时时间、重试次数,以及...

Global site tag (gtag.js) - Google Analytics