最近准备学习Dubbo,首选从dubbo官网开始,毕竟是国产的框架,官方文档也有中文版的,这就大大降低了阅读官方文档的难度。目前官方文档有两个版本,3.0版本和2.x版本。笔者阅读的是后者,所以运行的demo示例也是2.x版本的,就是文档中快速开始中的示例。笔者按照文档中的说明一步一步地创建好项目后,就是一直运行不起来(这里说明一下,笔者没有替换注册中心为zookeeper,使用的是dubbo内置的multicast广播注册中心),难道dubbo官网上的示例无法运行?笔者就开始进行各种搜索,断断续续花了好两天的时间,终于跑起来了。这里笔者就记录一下,以防各位采坑。
项目代码
项目搭建采用的pom.xml,包含了最基础的Spring核心包和dubbo包:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>dubbo</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-provider</artifactId>
<dependencies>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>2.7.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.0.RELEASE</version>
</dependency>
</dependencies>
</project>
服务提供者
服务接口DemoService.java:
package org.apache.dubbo.demo;
public interface DemoService {
String sayHello(String name);
}
服务接口实现DemoServiceImpl.java:
package org.apache.dubbo.demo.provider;
import org.apache.dubbo.demo.DemoService;
public class DemoServiceImpl implements DemoService {
public String sayHello(String name) {
return "Hello " + name;
}
}
服务提供者配置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="hello-world-app"/>
<dubbo:registry address="multicast://224.5.6.7:1234"/>
<dubbo:protocol name="dubbo" port="20880"/>
<dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService" version="1.0"/>
<bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl"/>
</beans>
服务提供者主程序Provider.java:
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Provider {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"provider.xml"});
context.start();
System.in.read();
}
}
服务消费者
首先拷贝服务提供者的接口DemoService.java(连同完整的包结构)到服务消费者项目中。 服务消费者配置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="consumer-of-helloworld-app"/>
<dubbo:registry address="multicast://224.5.6.7:1234"/>
<dubbo:reference id="demoService" interface="org.apache.dubbo.demo.DemoService" version="1.0"/>
</beans>
服务消费者主程序Consumer.java:
import org.apache.dubbo.demo.DemoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Consumer {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"consumer.xml"});
context.start();
DemoService demoService = (DemoService) context.getBean("demoService");
String hello = demoService.sayHello("world");
System.out.println(hello);
}
}
接下来先运行服务提供者的主程序,再运行服务消费者的主程序,这个时候肯定是希望能跑通程序看到正确的结果。但是不出意外的话,会报错误,程序无法正确运行。
报错信息
1、端口相关(qos-server can not bind localhost:22222)错误
严重: [DUBBO] qos-server can not bind localhost:22222, dubbo version: 2.7.12, current host: 192.168.112.1
java.net.BindException: Address already in use: bind
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:433)
at sun.nio.ch.Net.bind(Net.java:425)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:134)
at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:550)
at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1334)
at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:506)
at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:491)
at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:973)
at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:248)
at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:356)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
......
警告: [DUBBO] Fail to start qos server: , dubbo version: 2.7.12, current host: 192.168.112.1
java.net.BindException: Address already in use: bind
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:433)
at sun.nio.ch.Net.bind(Net.java:425)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:134)
at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:550)
at io.netty.channel.DefaultChannelPipeline$HeadContext.bind(DefaultChannelPipeline.java:1334)
at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:506)
at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:491)
at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:973)
at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:248)
at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:356)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
报错信息显示无法绑定到22222端口,正在使用中。这里参考Dubbo启动时qos-server can not bind localhost:22222错误解决博客进行解决,大致意思就是先启动的服务提供者已经绑定到22222端口了,后启动的服务消费者无法绑定到22222端口。所以将服务消费者的配置修改为:
<?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="consumer-of-helloworld-app">
<dubbo:parameter key="qos.enable" value="true" />
<dubbo:parameter key="qos.accept.foreign.ip" value="false" />
<dubbo:parameter key="qos.port" value="33333" />
</dubbo:application>
<dubbo:registry address="multicast://224.5.6.7:1234"/>
<dubbo:reference id="demoService" interface="org.apache.dubbo.demo.DemoService" version="1.0"/>
</beans>
如此一来,服务提供者和服务消费者就不会出现端口冲突的问题了。
2、调用服务提供者失败(Error creating bean with name ‘demoService’: FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: Failed to check the status of the service org.apache.dubbo.demo.DemoService.)
信息: [DUBBO] Receive multicast message: unsubscribe consumer://192.168.112.1/org.apache.dubbo.demo.DemoService?application=consumer-of-helloworld-app&category=providers,configurators,routers&dubbo=2.0.2&init=false&interface=org.apache.dubbo.demo.DemoService&methods=sayHello&pid=2828&qos.accept.foreign.ip=false&qos.enable=true&qos.port=33333&release=2.7.12&revision=1.0&side=consumer&sticky=false×tamp=1629040507971&version=1.0 from /192.168.0.104:1235, dubbo version: 2.7.12, current host: 192.168.112.1
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'demoService': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: Failed to check the status of the service org.apache.dubbo.demo.DemoService. No provider available for the service org.apache.dubbo.demo.DemoService:1.0 from the url dubbo://192.168.112.1/org.apache.dubbo.demo.DemoService?application=consumer-of-helloworld-app&dubbo=2.0.2&init=false&interface=org.apache.dubbo.demo.DemoService&methods=sayHello&pid=2828&qos.accept.foreign.ip=false&qos.enable=true&qos.port=33333®ister.ip=192.168.112.1&release=2.7.12&revision=1.0&side=consumer&sticky=false×tamp=1629040507971&version=1.0 to the consumer 192.168.112.1 use dubbo version 2.7.12
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:178)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:101)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1647)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getObjectForBeanInstance(AbstractAutowireCapableBeanFactory.java:1215)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:257)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1085)
at Consumer.main(Consumer.java:9)
Caused by: java.lang.IllegalStateException: Failed to check the status of the service org.apache.dubbo.demo.DemoService. No provider available for the service org.apache.dubbo.demo.DemoService:1.0 from the url dubbo://192.168.112.1/org.apache.dubbo.demo.DemoService?application=consumer-of-helloworld-app&dubbo=2.0.2&init=false&interface=org.apache.dubbo.demo.DemoService&methods=sayHello&pid=2828&qos.accept.foreign.ip=false&qos.enable=true&qos.port=33333®ister.ip=192.168.112.1&release=2.7.12&revision=1.0&side=consumer&sticky=false×tamp=1629040507971&version=1.0 to the consumer 192.168.112.1 use dubbo version 2.7.12
at org.apache.dubbo.config.ReferenceConfig.checkInvokerAvailable(ReferenceConfig.java:449)
at org.apache.dubbo.config.ReferenceConfig.init(ReferenceConfig.java:323)
at org.apache.dubbo.config.ReferenceConfig.get(ReferenceConfig.java:206)
at org.apache.dubbo.config.spring.ReferenceBean.getObject(ReferenceBean.java:68)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:171)
... 7 more
当dubbo新手遇到这样的问题时,往往是不知怎么回事。仔细看一下报错信息,大致是说找不到服务,无法创建DemoService对象。然后笔者就去对照着文档检查自己的代码和配置文件哪里有问题,可是检查了好几遍,都发现和官网上写的一模一样。笔者就去网上搜解决办法,也未能马上找到有效的解决方法。后来找到一篇有启发的文章,说是因为电脑安装了虚拟机的原因,这样电脑会有多个ip,导致服务提供者和服务消费者广播的IP不一致,服务消费者找不到接口,随后笔者去检查服务消费者请求地址中的ip,发现果然是虚拟机的一个ip,后来禁用掉虚拟机的两个适配器,只保留本机无线网卡工作。问题终于得以解决,服务消费者成功调用服务。 如果没有安装虚拟机软件的话,应该是不会出现这个问题的;如果安装虚拟机的话,希望可以注意一下吧。
|