1、定义
是个远程服务调用的分布式框架(告别Web Service模式中的WSdl,以服务者与消费者的方式在dubbo上注册)
2、分布式和集群的区别
小饭店原来只有一个厨师,切菜洗菜备料炒菜全干。后来客人多了,厨房一个厨师忙不过来,又请了个厨师,两个厨师都能炒一样的菜,这两个厨师的关系是集群。为了让厨师专心炒菜,把菜做到极致,又请了个配菜师负责切菜,备菜,备料,厨师和配菜师的关系是分布式,一个配菜师也忙不过来了,又请了个配菜师,两个配菜师关系是集群
3、功能
- 透明化的远程方法调用,就像调用本地方法一样调用远程方法,只需简单配置,没有任何api侵入。
- 软负载均衡及容错机制,可在内网替代F5等硬件负载均衡器,降低成本,减少单点、
- 服务自动注册与发现,不再需要写死服务提供方地址,注册中心基于接口名查询服务提供者的IP地址。并且能够平滑添加或删除服务提供者。
4、框架
节点角色说明:
- Provider:暴露服务的服务提供方。
- Consumer: 调用远程服务的服务消费方。
- Registry:服务注册与发现的注册中心。
- Monitor:统计服务的调用次数和调用时间的监控中心。
- Container:服务运行容器
运行步骤:
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
5、使用方法
Dubbo采用全Spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。如果不想使用Spring配置,可以通过API的方式进行调用(注解式,不推荐使用)
6、注册中心zookeeper(不建议使用multicast)
6.1、windows版
使用方法:下载解压即可,进入解压目录运行zkServer.cmd启动注册服务中心
截图:
6.2、MacOS
下载地址
使用方法:下载解压即可,进入解压目录运行zkServer.sh start启动注册服务中心
6.3、Linux
下载地址
使用方法:下载解压即可,进入解压目录运行zkServer.sh start启动注册服务中心
7、服务提供者
7.1、定义服务接口
该接口需单独打包,在服务提供方和消费方共享
package org.apache.dubbo.demo;
public interface DemoService {
String sayHello(String name);
}
7.2、服务提供方实现接口
对服务消费方隐藏实现
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;
}
}
7.3、用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-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="hello-world-app" />
<!-- 使用multicast广播注册中心暴露服务地址 -->
<dubbo:registry address="multicast://224.5.6.7:1234" />
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="org.apache.dubbo.demo.DemoService" ref="demoService" />
<!-- 和本地bean一样实现服务 -->
<bean id="demoService" class="org.apache.dubbo.demo.provider.DemoServiceImpl" />
</beans>
7.4、加载Spring配置,启动服务
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Provider {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring/dubbo-provider.xml"});
context.start();
System.in.read(); // 按任意键退出
}
}
或者使用springBoot启动
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("spring/dubbo-provider.xml")
public class DubboProviderApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(DubboProviderApplication.class, args);
}
}
8、服务消费者
applicationContext-dubbo.xml 中注册自己需要调用的接口。
8.1、通过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-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:application name="consumer-of-helloworld-app" />
<!-- 使用multicast广播注册中心暴露发现服务地址 -->
<dubbo:registry address="multicast://224.5.6.7:1234" />
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:reference id="demoService" interface="org.apache.dubbo.demo.DemoService" />
</beans>
8.2、加载Spring配置,并调用远程服务
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.apache.dubbo.demo.DemoService;
public class Consumer {
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring/dubbo-consumer.xml"});
context.start();
DemoService demoService = (DemoService)context.getBean("demoService"); // 获取远程服务代理
String hello = demoService.sayHello("world"); // 执行远程方法
System.out.println( hello ); // 显示调用结果
}
}
或者使用springBoot启动
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;
@SpringBootApplication
@ImportResource("spring/dubbo-consumer.xml")
public class DubboConsumerApplicaiton {
public static final Logger logger = LoggerFactory.getLogger(DubboConsumerApplicaiton.class);
public static void main(String[] args) {
SpringApplication.run(DubboConsumerApplicaiton.class, args);
}
}
并添加对应的restful接口提供接口访问
@RequestMapping("/demo")
public ModelAndView testDemo() {
ModelAndView modelAndView = new ModelAndView("index");
org.apache.dubbo.rpc.RpcContext.getContext().setAttachment(Constants.TAG_KEY, "gray");
modelAndView.addObject("result", demoService.sayHello("Dubbo Meetup"));
return modelAndView;
}
修改对应index页面
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Vertical centering in valid CSS</title>
<style type="text/css">
.text{text-align:center; }
</style>
</head>
<body>
<div class="text" style="margin-top:300px;font-size: 50px;">${result.msg}</div>
<div class="text" style="margin-top:30px;font-size: 35px;color:#5079bb;">From : ${result.userName}</div>
</body>
</html>
9、dubbo管理页面
下载地址
启动后访问 http://localhost:8080/dubbo-admin/
输入账号密码root/root
应用页面:
提供者页面:
消费者页面:
服务页面:
测试是否成功,只要看状态是否正常,就ok了 ….
provider-log:
2019-07-04 11:37:49,326 [DubboServerHandler-192.168.0.46:20880-thread-2] INFO org.apache.dubbo.demo.impl.DemoServiceImpl (DemoServiceImpl.java:31) - [DUBBO] [11:37:49] Hello Alterem., request from consumer: /192.168.0.46:52031, dubbo version: 2.7.0, current host: 192.168.0.46
10、使用Dubbo遇到的问题
10.1、org.springframework.beans.factory.BeanCreationException
原因分析:
Error creating bean with name 'mgmtFactoryInoutDetailsController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'goodsInoutServiceImpl' available
at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessPropertyValues(CommonAnnotationBeanPostProcessor.java:321)
解决方案
在dubbo-provider.xml添加对应的声明暴露服务
<dubbo:service interface="ue.biz.service.biz.GoodsInoutService" ref="goodsInoutServiceImpl"/>
在dubbo-consumer.xml添加对应的服务订阅
<dubbo:reference id="goodsInoutServiceImpl" interface="ue.biz.service.biz.GoodsInoutService"/>
10.2、org.apache.dubbo.rpc.RpcException
原因分析
No provider available from registry 120.79.246.86:2181 for service ue.biz.service.bas.EnterpriseUserService on consumer 192.168.0.63 use dubbo version 2.7.0, please check status of providers
解决方案
可能是因为providers没有启动,或者是provider对应暴露的服务被禁用,启动providers或者解除禁用即可
10.3、java.lang.IllegalStateException
原因分析
this web application instance has been stopped already.
所以,需要重启Tomcat的情况下才有可能发上,这是第一个出错条件。
Could not load [io.netty.channel.nio.NioEventLoop].
看这个不能直接推出问题产生条件,但是很明显是关于加载的。
解决方案
总结以上两点,通俗点讲,就是重启了工程(可能是因为直接修改代码,工程reload了), 并且,连过了数据库(登录等),才出现了上述报错信息。 原因是因为在tomcat重启的时候,之前的tomcat的线程还没有完全关闭,最新启动tomcat就会报这个异常。
10.4、org.apache.dubbo.remoting.TimeoutException
原因分析
org.apache.dubbo.remoting.TimeoutException: Waiting server-side response timeout by scan timer. start time: 2019-07-04 15:05:41.363, end time: 2019-07-04 15:05:51.388, client elapsed: 94 ms, server elapsed: 9931 ms, timeout: 10000 ms, request: Request [id=0, version=2.0.2, twoway=true, event=false, broken=false, data=RpcInvocation [methodName=find, parameterTypes=[class ue.biz.entity.sys.Permission$Type], arguments=[url], attachments={path=ue.biz.service.sys.PermissionService
解决方案
在dubbo-provider.xml增加超时时间
<dubbo:provider delay="-1" timeout="10000" retries="0"/>