dubbo是一个rpc框架,提供了远程方法调用的功能 需要3个角色:注册中心、服务提供方、服务消费方 注册中心用:nacos 服务提供方名称:dubbo-provider-demo 服务消费方名称:dubbo-consumer-demo dubbo使用spring装配有两种配置方法,注解驱动和spring xml文件配置,这里使用xml文件
1、pom文件添加依赖
<dubbo.version>2.6.9</dubbo.version>
<dubbo.spring.version>1.0.11</dubbo.spring.version>
<dubbo.registry.nacos.version>2.6.7</dubbo.registry.nacos.version>
<!-- dubbo依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>${dubbo.version}</version>
</dependency>
<!-- dubbo使用spring装配方式 -->
<dependency>
<groupId>com.alibaba.spring</groupId>
<artifactId>spring-context-support</artifactId>
<version>${dubbo.spring.version}</version>
</dependency>
<!-- dubbo nacos registry依赖 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo-registry-nacos</artifactId>
<version>${dubbo.registry.nacos.version}</version>
</dependency>
2、在webapp2_module1模块 1)添加包com.study.module1.dubbo.resource 2)在该包下,添加服务接口,DemoService.java
package com.study.module1.dubbo.resource;
public interface DemoService {
String echo(String msg);
}
3)添加包com.study.module1.dubbo.resource.impl 4)在该包下,添加服务接口实现类,DemoServiceImpl.java
package com.study.module1.dubbo.resource.impl;
import com.alibaba.dubbo.rpc.RpcContext;
import com.study.module1.dubbo.resource.DemoService;
public class DemoServiceImpl implements DemoService {
@Override
public String echo(String msg) {
RpcContext rpcContext = RpcContext.getContext();
// 获取当前服务配置信息
String application = RpcContext.getContext().getUrl().getParameter("application");
return String.format("Service [name :%s , port : %d] %s say : Hello,%s",
application,
rpcContext.getLocalPort(),
rpcContext.getMethodName(), msg);
}
}
3、webapp2_web模块src/main/resources 1)添加服务提供方配置文件,spring-dubbo-provider.xml
<?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:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="dubbo-provider-demo"/>
<!-- 使用 Nacos 注册中心 -->
<dubbo:registry address="nacos://172.0.0.1:8848"/>
<!-- 如果要使用自己创建的命名空间可以使用下面配置 -->
<!-- <dubbo:registry address="nacos://127.0.0.1:8848?namespace=5cbb70a5-xxx-xxx-xxx-d43479ae0932" /> -->
<!-- 用dubbo协议在随机端口暴露服务 -->
<dubbo:protocol name="dubbo" port="-1"/>
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.study.module1.dubbo.resource.DemoService" ref="demoService" version="1.0.0"/>
<!-- 和本地bean一样实现服务 -->
<bean id="demoService" class="com.study.module1.dubbo.resource.impl.DemoServiceImpl"/>
</beans>
2)添加服务消费方配置文件,spring-dubbo-consumer.xml
<?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:dubbo="http://dubbo.apache.org/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo
http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="dubbo-consumer-demo"/>
<!-- 使用 Nacos 注册中心 -->
<dubbo:registry address="nacos://127.0.0.1:8848"/>
<!-- 如果要使用自己创建的命名空间可以使用下面配置 -->
<!-- <dubbo:registry address="nacos://127.0.0.1:8848?namespace=5cbb70a5-xxx-xxx-xxx-d43479ae0932" /> -->
<!-- 引用服务接口 -->
<dubbo:reference id="dubboConsumer" interface="com.study.module1.dubbo.resource.DemoService" version="1.0.0"/>
</beans>
3)applicationContext.xml添加文件引用
<import resource="classpath:/spring-dubbo-provider.xml"/>
<import resource="classpath:/spring-dubbo-consumer.xml"/>
注:实际只能配置使用一个,要么服务方要么消费方
4、在src/test/java下添加测试类,DubboTest.java
package webapp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import com.study.base.util.ApplicationContextHolder;
import com.study.module1.dubbo.resource.DemoService;
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = { "classpath:applicationContext.xml", "classpath:spring-mvc.xml" })
@ActiveProfiles("dev")
public class DubboTest {
@Test
public void test() throws Exception {
DemoService demo = ApplicationContextHolder.getBean("dubboConsumer", DemoService.class);
String result = demo.echo("我是谁");
System.out.println(result);
System.out.println("111111111111111111111111");
Thread.sleep(60 * 1000);
}
}
5、测试方法
1)起一个服务,配置为服务提供方,放到tomcat中启动
2)本地项目配置为服务消费方,运行测试方法
日志打印出:Service [name :dubbo-provider-demo , port : 20880] echo say : Hello,我是谁
查看nacos控制台,都注册上了:
6、遇到的问题 1)pom文件中 <!-- dubbo nacos registry依赖 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>${dubbo.registry.nacos.version}</version> </dependency> 版本不能用2.6.9,因为会报错,原因是这个版本没有自动依赖nacos-client包。。。
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:189)
at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:131)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access0(ParentRunner.java:66)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:293)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: java.lang.IllegalStateException: Failed to load extension class(interface: interface com.alibaba.dubbo.registry.RegistryFactory, class line: com.alibaba.dubbo.registry.nacos.NacosRegistryFactory) in jar:file:/C:/Users/User/.m2/repository/com/alibaba/dubbo-registry-nacos/2.6.9/dubbo-registry-nacos-2.6.9.jar!/META-INF/dubbo/com.alibaba.dubbo.registry.RegistryFactory, cause: com/alibaba/nacos/api/exception/NacosException
at com.alibaba.dubbo.common.extension.ExtensionLoader.loadResource(ExtensionLoader.java:634)
at com.alibaba.dubbo.common.extension.ExtensionLoader.loadDirectory(ExtensionLoader.java:604)
at com.alibaba.dubbo.common.extension.ExtensionLoader.loadExtensionClasses(ExtensionLoader.java:586)
at com.alibaba.dubbo.common.extension.ExtensionLoader.getExtensionClasses(ExtensionLoader.java:561)
at com.alibaba.dubbo.common.extension.ExtensionLoader.getExtensionClass(ExtensionLoader.java:549)
at com.alibaba.dubbo.common.extension.ExtensionLoader.hasExtension(ExtensionLoader.java:333)
at com.alibaba.dubbo.config.AbstractInterfaceConfig.loadRegistries(AbstractInterfaceConfig.java:185)
at com.alibaba.dubbo.config.ServiceConfig.doExportUrls(ServiceConfig.java:358)
at com.alibaba.dubbo.config.ServiceConfig.doExport(ServiceConfig.java:319)
at com.alibaba.dubbo.config.ServiceConfig.export(ServiceConfig.java:217)
at com.alibaba.dubbo.config.spring.ServiceBean.export(ServiceBean.java:266)
at com.alibaba.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:106)
at com.alibaba.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:53)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:393)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:347)
at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:883)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:545)
at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:130)
at org.springframework.test.context.web.AbstractGenericWebContextLoader.loadContext(AbstractGenericWebContextLoader.java:61)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:281)
at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:249)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
... 26 more
Caused by: java.lang.NoClassDefFoundError: com/alibaba/nacos/api/exception/NacosException
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:348)
at com.alibaba.dubbo.common.extension.ExtensionLoader.loadResource(ExtensionLoader.java:631)
... 51 more
Caused by: java.lang.ClassNotFoundException: com.alibaba.nacos.api.exception.NacosException
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 54 more
2)在实际使用中服务提供方和服务消费方是两个不同的项目
那么服务消费方如何获取这个服务接口类,DemoService.class?引入对方的jar包?
3)nacos控制台-服务管理,下面分为服务列表和订阅者列表,这个订阅者列表是干什么的呢?
这个订阅者列表不是指消费者列表,而是指主动向Nacos Server发起事件监听的订阅者,比如健康检查、服务变更等事件监听的订阅者,具体可查看NacosDiscoveryEndpoint.nacosDiscovery()方法中是通过EventDispatcher去获取订阅者列表和发布事件。新版本才加了这么个订阅者列表,老版本可以订阅默认端点查看订阅者列表:http://127.0.0.1:9000/actuator/nacos-discovery
参考资料:https://nacos.io/zh-cn/docs/use-nacos-with-dubbo.html
注:最新代码上传至https://github.com/csj50/webapp2.git