首页 > 其他分享 >初识Dubbo

初识Dubbo

时间:2022-12-22 11:33:39浏览次数:56  
标签:Dubbo java dubbo jar springframework 初识 beans org


目录

​​Dubbo能够做什么​​

​​Dubbo架构图​​

​​入门案例​​

​​在Dubbo中引入注册中心​​

​​关于Dubbo Container​​

​​Dubbo多协议支持​​

​​Dubbo多注册中心的支持​​

​​Dubbo启动检查配置​​

​​Dubbo集群的访问​​


Dubbo能够做什么

  1. 远程调用;
  2. 目录服务;
  3. 集群;
  4. 监控;

Dubbo架构图

初识Dubbo_ide

官网上也已经说的很清楚了:

节点角色说明

节点

角色说明

​Provider​

暴露服务的服务提供方

​Consumer​

调用远程服务的服务消费方

​Registry​

服务注册与发现的注册中心

​Monitor​

统计服务的调用次数和调用时间的监控中心

​Container​

服务运行容器

调用关系说明

  1. 服务容器负责启动,加载,运行服务提供者。
  2. 服务提供者在启动时,向注册中心注册自己提供的服务。
  3. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  4. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  5. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  6. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

入门案例

首先用idea分别创建一个服务端和客户端的工程:

初识Dubbo_spring_02

初识Dubbo_spring_03

初识Dubbo_ide_04

再在服务端工程中创建两个模块server-api和server-provider,api模块主要是对外提供的api,provider是对这些api的一些实现:

初识Dubbo_ide_05

初识Dubbo_ide_06

删除多余的src目录:

初识Dubbo_spring_07

在server-api模块中定义一个接口:

初识Dubbo_ide_08

在server-provider中需要实现IHello接口,这个时候在server-provider模块中需要依赖server-api:

初识Dubbo_xml_09


在server-provider中具体实现IHello:

初识Dubbo_ide_10

将dubboserver安装到本地:

初识Dubbo_ide_11

在dubboclient客户端中引入server-api的依赖:

初识Dubbo_ide_12

客户端获取了依赖后就可以直接使用了:

初识Dubbo_ide_13

目前架构图如下:

初识Dubbo_spring_14

目前Client只拿到了IHello接口,但是实现类在server-provider中。如果是使用的比如RMI那就需要服务端发布服务,客户端looking获取服务的代理对象然后进行调用。使用Dubbo也是一样的,在server-provider中依赖Dubbo的jar包:

初识Dubbo_spring_15

Dubbo是默认基于Spring进行扩展的,所以在依赖了Dubob的jar之后可以看到同时也依赖了Spring的包(后续可以exclusion):

初识Dubbo_ide_16

所以我们可以在这里引用Spring的配置文件来对服务进行发布。

server-provider中新增resource作为资源目录:

初识Dubbo_spring_17

初识Dubbo_xml_18

初识Dubbo_spring_19

在resource中新建xml文件:dubbo-server.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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">


</beans>

接下来需要基于Dubbo固定的配置完成服务的发布:

<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--提供方信息,定义当前项目对外发布的一些内容信息,name尽量保证唯一(这里没有强制唯一),owner表示维护者-->
<dubbo:application name="dubbo-server" owner="dongguabai"/>

<!--注册中心-Dongguabai,N/A表示不需要依赖注册中心-->
<dubbo:registry address="N/A"/>

<!--发布的协议名称(默认dubbo协议)、端口-->
<dubbo:protocol port="20880" name="dubbo"/>

<!--当前创建服务的接口地址;ref指明实现;-->
<dubbo:service interface="dongguabai.dubbo.IHello" ref="helloService"/>

<!--实现Bean-->
<bean id="helloService" class="dongguabai.dubbo.HelloImpl"/>

</beans>

编写一个简单的启动类:

package dongguabai.dubbo;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
* @author Dongguabai
* @date 2018/11/15 9:52
*/
public class App {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-server.xml");
context.start();
System.in.read();
}
}

从控制台中可以看到已经发布了一个本地服务:

初识Dubbo_spring_20

在消费端如果需要使用Dubbo服务的话,需要引入相关依赖:

初识Dubbo_xml_21

同时也需要新增resource作为资源目录:

初识Dubbo_spring_22

增加dubbo-cli.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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--提供方信息,定义当前项目对外发布的一些内容信息,name尽量保证唯一(这里没有强制唯一),owner表示维护者-->
<dubbo:application name="dubbo-cli" owner="dongguabai"/>

<!--注册中心-Dongguabai,N/A表示不需要依赖注册中心-->
<dubbo:registry address="N/A"/>

<dubbo:reference interface="dongguabai.dubbo.IHello" id="helloService" url="dubbo://172.30.57.63:20880/dongguabai.dubbo.IHello"/>

</beans>

在dubboclient中远程调用服务:

package dongguabai.dubbo;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
* @author Dongguabai
* @date 2018/11/15 9:52
*/
public class App {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-cli.xml");
//获取IHello的远程代理对象
IHello helloService = (IHello) context.getBean("helloService");

String s = helloService.sayHello("张三");
System.out.println(s);
System.in.read();
}
}

运行结果,基于Netty完成远程通信,基于TCP协议完成数据交互,调用成功:

初识Dubbo_ide_23

虽然调用成功,但是现有还是有点问题,server和client是通过url去连接的,没有使用注册中心,相当于还是点对点,也没有办法对地址进行管理。

在Dubbo中引入注册中心

Dubbo是支持注册中心的:

初识Dubbo_xml_24

官方推荐使用ZooKeeper为注册中心。

在duboserver中引入相关的ZooKeeper的依赖和ZKClient依赖(Dubbo默认使用ZKClient):

初识Dubbo_spring_25

修改dubboserver的配置文件,加入注册中心中发布服务:

初识Dubbo_spring_26

再启动dubboserver发布服务,进入ZooKeeper客户端:

初识Dubbo_spring_27

在dubboclient中添加相应的依赖:

初识Dubbo_ide_28

修改dubboclient的配置文件,加入注册中心地址:

<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--提供方信息,定义当前项目对外发布的一些内容信息,name尽量保证唯一(这里没有强制唯一),owner表示维护者-->
<dubbo:application name="dubbo-server" owner="dongguabai"/>

<!--注册中心-Dongguabai,N/A表示不需要依赖注册中心-->
<dubbo:registry address="zookeeper://192.168.220.137:2181"/>

<!--当前创建服务的接口地址;ref指明实现;-->
<dubbo:reference interface="dongguabai.dubbo.IHello" id="helloService"/>

</beans>

启动dubboclient:

初识Dubbo_xml_29

程序运行成功。

进入ZooKeeper客户端:

初识Dubbo_spring_30

Dubbo就是基于ZK的节点来管理协议地址。生成了一个叫/dubbo的namespace。在/dubbo下就是interface。在interface下有四个子节点consumers, configurators, routers, providers。 consumers表示当前正在消费的消费端信息,比如现在dubboclient正在调用这个服务,这时候会在consumers上注册一个地址,可以在监控平台上看到这样一个地址;configurators是配置;routers是路由;providers是提供服务的路径:

初识Dubbo_spring_31

其实这就是一个协议地址,Dubbo是基于url驱动的,所以能够看到这个地址后面带了很多内容。我们会通过url将版本信息传过去,这样消费端就知道去调用哪个版本。

在dubboserver停止后,providers的节点内容也消失了:

初识Dubbo_spring_32

启动dubboserver,让消费端一直消费,这时候可以看看consumers的节点内容:

初识Dubbo_ide_33

初识Dubbo_spring_34

那么是不是客户端每次访问都需要访问ZooKeeper呢,不是的,在Dubbo中会缓存地址,比如我们可以在dubboclient的配置文件配置缓存文件:

初识Dubbo_ide_35

这个文件中会缓存相应的服务信息,可以看到在H盘下生成了这个文件:

初识Dubbo_spring_36

文件内存储了相应的信息:

#Dubbo Registry Cache
#Thu Nov 15 20:58:42 CST 2018
dongguabai.dubbo.IHello=empty\://172.30.57.63/dongguabai.dubbo.IHello?application\=dubbo-server&category\=configurators&dubbo\=2.5.3&interface\=dongguabai.dubbo.IHello&methods\=sayHello&owner\=dongguabai&pid\=19832&revision\=1.0-SNAPSHOT&side\=consumer×tamp\=1542286721769 empty\://172.30.57.63/dongguabai.dubbo.IHello?application\=dubbo-server&category\=routers&dubbo\=2.5.3&interface\=dongguabai.dubbo.IHello&methods\=sayHello&owner\=dongguabai&pid\=19832&revision\=1.0-SNAPSHOT&side\=consumer×tamp\=1542286721769 dubbo\://172.30.57.63\:20880/dongguabai.dubbo.IHello?anyhost\=true&application\=dubbo-server&dubbo\=2.5.3&interface\=dongguabai.dubbo.IHello&methods\=sayHello&owner\=dongguabai&pid\=19032&side\=provider×tamp\=1542286472249

ZK宕掉后就可以从文件中读取内容,Dubbo有一个定时任务去更新缓存。

关于Dubbo Container

Dubbo的启动是不需要依赖于外部的容器(比如Tomcat,Jetty)的,Dubbo提供了一种基于Main的启动:

public class Main {
public static void main(String[] args) throws IOException {

//默认情况下会使用spring容器来启动服务
com.alibaba.dubbo.container.Main.main(
new String[]{"spring","log4j"});
}
}

Dubbo支持Spring、Jetty、Log4j容器,默认情况下会基于Spring容器启动。其实这个Main.main(args)和之前的示例中基于ClassPathXmlApplicationContext启动一样。

main()方法的逻辑也很简单:

初识Dubbo_spring_37

会循环args参数往List<Container>中添加Container,直接看看SpringContainer:

初识Dubbo_ide_38

也是基于ClassPathXmlApplicationContext来的:

初识Dubbo_xml_39

可以看到默认的配置文件的路径是classpath下的META-INF/spring/下,在resource下把这个路径和文件创建好:

初识Dubbo_xml_40

接下来启动Dubbo:

初识Dubbo_xml_41

可以看到启动成功:

初识Dubbo_xml_42

为了方便,增加一个日志配置文件:

log4j.rootLogger=info, stdout

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n

初识Dubbo_spring_43

Dubbo多协议支持

Dubbo能够支持很多种协议,比如RMI,Hessian、WebService、Http、Thrift和默认的Dubbo协议(基于NIO)。支持众多的协议能够让Dubbo平缓的迁移实现服务治理,不需要修改原本的协议服务;也可以让我们针对特定的接口使用特定的协议。

接下来演示指定Hessian协议。

在dubboserver中指定protocol为hessian:

初识Dubbo_ide_44

引入Hessian相关的依赖(Hessian是基于Http的一种协议,所以需要Servlet和Servlet容器):

初识Dubbo_spring_45

启动dubboserver:

初识Dubbo_xml_46

 

再看看ZooKeeper客户端:

初识Dubbo_ide_47

dubboclient想要调用这个服务的话也要添加相应的依赖:

初识Dubbo_spring_48

在配置文件中指定protocl为hessian,这时候通信协议是基于hessian来通信。运行dubboclient调用dubboserver,调用成功:

初识Dubbo_spring_49

Dubbo还可以针对不同的服务使用不同的协议。

这里在dubboserver中再定义一个接口:

初识Dubbo_xml_50

和实现类:

初识Dubbo_ide_51

再配置文件中加入相应的配置:

初识Dubbo_spring_52

也就是现在在两个不同的接口对应不同的协议,将dubboserver发布,在控制台中可以看到发布了一个基于Dubbo协议和一个基于Hessian协议的服务:

初识Dubbo_ide_53

初识Dubbo_ide_54

进入ZooKeeper客户端:

初识Dubbo_ide_55

初识Dubbo_spring_56

初识Dubbo_ide_57

其实主要是协议头不一样。

因为新增了服务接口,将dubboserver重新发布:

初识Dubbo_xml_58

客户端Reimport即可。

修改客户端配置文件:

初识Dubbo_spring_59

运行dubboclient调用dubboserver:

package dongguabai.dubbo;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
* @author Dongguabai
* @date 2018/11/15 9:52
*/
public class App {
public static void main(String[] args) throws IOException {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("dubbo-cli.xml");
//获取IHello的远程代理对象
IHello helloService = (IHello) context.getBean("helloService");
String s = helloService.sayHello("张三");

IProtocol protocolService = (IProtocol) context.getBean("protocolService");

System.out.println("调用helloService::"+s);
System.out.println("调用protocolService::"+protocolService.sayGood("李四"));
System.in.read();
}
}

控制台出现了异常:

H:\dev\Java\jdk1.8.0_65\bin\java "-javaagent:H:\idea\IntelliJ IDEA 2017.1.5\lib\idea_rt.jar=9576:H:\idea\IntelliJ IDEA 2017.1.5\bin" -Dfile.encoding=UTF-8 -classpath H:\dev\Java\jdk1.8.0_65\jre\lib\charsets.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\deploy.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\access-bridge-64.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\cldrdata.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\dnsns.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\jaccess.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\jfxrt.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\localedata.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\nashorn.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\sunec.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\sunjce_provider.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\sunmscapi.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\sunpkcs11.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\zipfs.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\javaws.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\jce.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\jfr.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\jfxswt.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\jsse.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\management-agent.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\plugin.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\resources.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\rt.jar;H:\idea_demo1\dubboclient\target\classes;H:\maven\repository\dongguabai\dubbo\server-api\1.0-SNAPSHOT\server-api-1.0-SNAPSHOT.jar;H:\maven\repository\com\alibaba\dubbo\2.5.3\dubbo-2.5.3.jar;H:\maven\repository\org\springframework\spring\2.5.6.SEC03\spring-2.5.6.SEC03.jar;H:\maven\repository\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;H:\maven\repository\org\javassist\javassist\3.15.0-GA\javassist-3.15.0-GA.jar;H:\maven\repository\org\jboss\netty\netty\3.2.5.Final\netty-3.2.5.Final.jar;H:\maven\repository\org\apache\zookeeper\zookeeper\3.4.10\zookeeper-3.4.10.jar;H:\maven\repository\org\slf4j\slf4j-api\1.6.1\slf4j-api-1.6.1.jar;H:\maven\repository\org\slf4j\slf4j-log4j12\1.6.1\slf4j-log4j12-1.6.1.jar;H:\maven\repository\log4j\log4j\1.2.16\log4j-1.2.16.jar;H:\maven\repository\jline\jline\0.9.94\jline-0.9.94.jar;H:\maven\repository\io\netty\netty\3.10.5.Final\netty-3.10.5.Final.jar;H:\maven\repository\com\101tec\zkclient\0.10\zkclient-0.10.jar;H:\maven\repository\com\caucho\hessian\4.0.38\hessian-4.0.38.jar;H:\maven\repository\javax\servlet\servlet-api\2.5\servlet-api-2.5.jar;H:\maven\repository\org\mortbay\jetty\jetty\6.1.26\jetty-6.1.26.jar;H:\maven\repository\org\mortbay\jetty\jetty-util\6.1.26\jetty-util-6.1.26.jar;H:\maven\repository\org\mortbay\jetty\servlet-api\2.5-20081211\servlet-api-2.5-20081211.jar dongguabai.dubbo.App
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloService': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalStateException: Failed to check the status of the service dongguabai.dubbo.IHello. No provider available for the service dongguabai.dubbo.IHello from the url zookeeper://192.168.220.137:2181/com.alibaba.dubbo.registry.RegistryService?application=dubbo-server&dubbo=2.5.3&interface=dongguabai.dubbo.IHello&methods=sayHello&owner=dongguabai&pid=18416&protocol=dubbo&revision=1.0-SNAPSHOT&side=consumer×tamp=1542341313723 to the consumer 172.30.57.63 use dubbo version 2.5.3
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport$1.run(FactoryBeanRegistrySupport.java:127)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:116)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:91)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1288)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:217)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:880)
at dongguabai.dubbo.App.main(App.java:15)
Caused by: java.lang.IllegalStateException: Failed to check the status of the service dongguabai.dubbo.IHello. No provider available for the service dongguabai.dubbo.IHello from the url zookeeper://192.168.220.137:2181/com.alibaba.dubbo.registry.RegistryService?application=dubbo-server&dubbo=2.5.3&interface=dongguabai.dubbo.IHello&methods=sayHello&owner=dongguabai&pid=18416&protocol=dubbo&revision=1.0-SNAPSHOT&side=consumer×tamp=1542341313723 to the consumer 172.30.57.63 use dubbo version 2.5.3
at com.alibaba.dubbo.config.ReferenceConfig.createProxy(ReferenceConfig.java:420)
at com.alibaba.dubbo.config.ReferenceConfig.init(ReferenceConfig.java:300)
at com.alibaba.dubbo.config.ReferenceConfig.get(ReferenceConfig.java:138)
at com.alibaba.dubbo.config.spring.ReferenceBean.getObject(ReferenceBean.java:65)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport$1.run(FactoryBeanRegistrySupport.java:121)
... 9 more

Process finished with exit code 1

显示协议版本不对,原来是两个服务的协议写反了,重新修改后再调用:

初识Dubbo_spring_60

Dubbo还可以让一个接口支持两种协议。

在dubboserver配置文件中(其实Dubbo就是使用一个for循环):

初识Dubbo_ide_61

再来启动dubboserver,出现了异常:

H:\dev\Java\jdk1.8.0_65\bin\java "-javaagent:H:\idea\IntelliJ IDEA 2017.1.5\lib\idea_rt.jar=9888:H:\idea\IntelliJ IDEA 2017.1.5\bin" -Dfile.encoding=UTF-8 -classpath H:\dev\Java\jdk1.8.0_65\jre\lib\charsets.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\deploy.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\access-bridge-64.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\cldrdata.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\dnsns.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\jaccess.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\jfxrt.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\localedata.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\nashorn.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\sunec.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\sunjce_provider.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\sunmscapi.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\sunpkcs11.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\ext\zipfs.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\javaws.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\jce.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\jfr.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\jfxswt.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\jsse.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\management-agent.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\plugin.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\resources.jar;H:\dev\Java\jdk1.8.0_65\jre\lib\rt.jar;H:\idea_demo1\dubboserver\server-provider\target\classes;H:\idea_demo1\dubboserver\server-api\target\classes;H:\maven\repository\com\alibaba\dubbo\2.5.3\dubbo-2.5.3.jar;H:\maven\repository\org\springframework\spring\2.5.6.SEC03\spring-2.5.6.SEC03.jar;H:\maven\repository\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;H:\maven\repository\org\javassist\javassist\3.15.0-GA\javassist-3.15.0-GA.jar;H:\maven\repository\org\jboss\netty\netty\3.2.5.Final\netty-3.2.5.Final.jar;H:\maven\repository\org\apache\zookeeper\zookeeper\3.4.10\zookeeper-3.4.10.jar;H:\maven\repository\org\slf4j\slf4j-api\1.6.1\slf4j-api-1.6.1.jar;H:\maven\repository\org\slf4j\slf4j-log4j12\1.6.1\slf4j-log4j12-1.6.1.jar;H:\maven\repository\log4j\log4j\1.2.16\log4j-1.2.16.jar;H:\maven\repository\jline\jline\0.9.94\jline-0.9.94.jar;H:\maven\repository\io\netty\netty\3.10.5.Final\netty-3.10.5.Final.jar;H:\maven\repository\com\101tec\zkclient\0.10\zkclient-0.10.jar;H:\maven\repository\com\caucho\hessian\4.0.38\hessian-4.0.38.jar;H:\maven\repository\javax\servlet\servlet-api\2.5\servlet-api-2.5.jar;H:\maven\repository\org\mortbay\jetty\jetty\6.1.26\jetty-6.1.26.jar;H:\maven\repository\org\mortbay\jetty\jetty-util\6.1.26\jetty-util-6.1.26.jar;H:\maven\repository\org\mortbay\jetty\servlet-api\2.5-20081211\servlet-api-2.5-20081211.jar dongguabai.dubbo.MyMain
log4j:WARN No appenders could be found for logger (com.alibaba.dubbo.common.logger.LoggerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dongguabai.dubbo.IHello': Cannot resolve reference to bean 'hessian' while setting bean property 'protocols' with key [0]; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'hessian' is defined
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:275)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:104)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveManagedList(BeanDefinitionValueResolver.java:287)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:126)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1245)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1010)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:472)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
at java.security.AccessController.doPrivileged(Native Method)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:308)
at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:947)
at org.springframework.context.support.AbstractApplicationContext.registerListeners(AbstractApplicationContext.java:701)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:377)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
at com.alibaba.dubbo.container.spring.SpringContainer.start(SpringContainer.java:50)
at com.alibaba.dubbo.container.Main.main(Main.java:80)
at dongguabai.dubbo.MyMain.main(MyMain.java:12)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'hessian' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:387)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:971)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:246)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:269)
... 23 more

Process finished with exit code 1

这样使用的话,就必须要声明协议,在配置文件中添加:

初识Dubbo_xml_62

再来发布服务:

初识Dubbo_ide_63

在ZooKeeper客户端中,一个接口发布了两个地址,可以看到两个不同的协议:

初识Dubbo_spring_64

在客户端中进行调用。修改客户端配置文件:

初识Dubbo_xml_65

调用:

初识Dubbo_ide_66

调用成功:

初识Dubbo_xml_67

Dubbo多注册中心的支持

也就是说在客户端或者服务端可以配置多个注册中心。

修改subboserver配置文件:

初识Dubbo_xml_68

服务接口指定注册中心,这样对应的服务只会发布到指定的注册中心。这样的好处就是比如有些网站需要中英文支持,我们可以中文的服务发布到中文的ZK,英文的服务发布到英文的ZK。

启动服务:

初识Dubbo_xml_69

注意这两个不同的注册中心就不是一个集群了。

Dubbo启动检查配置

有时候Dubbo服务可能会出现循环依赖的情况,即Client本身也是一个Server。比如商品和用户服务,商品服务可能需要调用用户服务,用户服务也会需要调用商品服务。这就存在了相互调用,也就是循环依赖问题。在启动客户端的时候如果没有服务会出现异常:

初识Dubbo_xml_70

在客户端可以配置check="false":

初识Dubbo_ide_71

这样客户端就会正常启动了:

初识Dubbo_xml_72

这样可以解决循环依赖的问题。

Dubbo集群的访问

之前介绍过了Dubbo可以解决负载均衡的问题,即我们可以对Server端进行水平扩容。即在dubboserver中发布多个服务节点。Dubbo会通过负载均衡算法完成对服务的路由。

这里简单演示一下,定义两个新的配置文件dubbo-cluser1.xml和dubbo-cluser2.xml:

初识Dubbo_xml_73

<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--提供方信息,定义当前项目对外发布的一些内容信息,name尽量保证唯一(这里没有强制唯一),owner表示维护者-->
<dubbo:application name="dubbo-server" owner="dongguabai"/>

<!--注册中心-Dongguabai,N/A表示不需要依赖注册中心-->
<!--注意要声明id-->
<dubbo:registry id="zk1" address="zookeeper://192.168.220.137:2181"/>

<!--发布的协议名称(默认dubbo协议)、端口-->
<dubbo:protocol port="20881" name="dubbo"/>

<!--当前创建服务的接口地址;ref指明实现;-->
<dubbo:service interface="dongguabai.dubbo.IHello" ref="helloService" protocol="dubbo" registry="zk1"/>
<!--当前创建服务的接口地址;ref指明实现;-->
<dubbo:service interface="dongguabai.dubbo.IProtocol" ref="protocolService" protocol="dubbo" registry="zk1"/>

<!--实现Bean-->
<bean id="helloService" class="dongguabai.dubbo.HelloImpl"/>
<!--实现Bean-->
<bean id="protocolService" class="dongguabai.dubbo.ProtocolImpl"/>

</beans>
<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--提供方信息,定义当前项目对外发布的一些内容信息,name尽量保证唯一(这里没有强制唯一),owner表示维护者-->
<dubbo:application name="dubbo-server" owner="dongguabai"/>

<!--注册中心-Dongguabai,N/A表示不需要依赖注册中心-->
<!--注意要声明id-->
<dubbo:registry id="zk1" address="zookeeper://192.168.220.137:2181"/>

<!--发布的协议名称(默认dubbo协议)、端口-->
<dubbo:protocol port="20882" name="dubbo"/>

<!--当前创建服务的接口地址;ref指明实现;-->
<dubbo:service interface="dongguabai.dubbo.IHello" ref="helloService" protocol="dubbo" registry="zk1"/>
<!--当前创建服务的接口地址;ref指明实现;-->
<dubbo:service interface="dongguabai.dubbo.IProtocol" ref="protocolService" protocol="dubbo" registry="zk1"/>

<!--实现Bean-->
<bean id="helloService" class="dongguabai.dubbo.HelloImpl"/>
<!--实现Bean-->
<bean id="protocolService" class="dongguabai.dubbo.ProtocolImpl"/>

</beans>

新建两个启动类App1和App2:

初识Dubbo_ide_74

初识Dubbo_ide_75

初识Dubbo_xml_76

分别启动App1和App2,然后在ZooKeeper客户端发现同一个服务存在了两个地址,只是端口不同:

初识Dubbo_xml_77

客户端获取两个地址就能够使用负载均衡的机制完成负载了。

为了看出负载效果,新建一个IHello实现类:

初识Dubbo_ide_78

在cluster2中使用HelloImpl2:

初识Dubbo_xml_79

在客户端中循环调用:

初识Dubbo_xml_80

控制台输出:

初识Dubbo_spring_81

可以看到调用的地址会有变化,默认情况Dubbo是基于随机负载。

在Dubbo中定义了一个LoadBalance接口:

初识Dubbo_spring_82

会把从远程服务端拿过来的List进行选取。默认实现是RandomLoadBalance:

/*
* Copyright 1999-2011 Alibaba Group.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.dubbo.rpc.cluster.loadbalance;

import java.util.List;
import java.util.Random;

import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;

/**
* random load balance.
*
* @author qianlei
* @author william.liangf
*/
public class RandomLoadBalance extends AbstractLoadBalance {

public static final String NAME = "random";

private final Random random = new Random();

protected <T> Invoker<T> doSelect(List<Invoker<T>> invokers, URL url, Invocation invocation) {
int length = invokers.size(); // 总个数
int totalWeight = 0; // 总权重
boolean sameWeight = true; // 权重是否都一样
for (int i = 0; i < length; i++) {
int weight = getWeight(invokers.get(i), invocation);
totalWeight += weight; // 累计总权重
if (sameWeight && i > 0
&& weight != getWeight(invokers.get(i - 1), invocation)) {
sameWeight = false; // 计算所有权重是否一样
}
}
if (totalWeight > 0 && ! sameWeight) {
// 如果权重不相同且权重大于0则按总权重数随机
int offset = random.nextInt(totalWeight);
// 并确定随机值落在哪个片断上
for (int i = 0; i < length; i++) {
offset -= getWeight(invokers.get(i), invocation);
if (offset < 0) {
return invokers.get(i);
}
}
}
// 如果权重相同或权重为0则均等随机
return invokers.get(random.nextInt(length));
}

}

这里会根据权重进行计算,也就是说我们可以根据不同的地址设置不同的权重。最后得到随机的结果值后返回调用服务。

 

Demo源码地址:​​https://github.com/Dongguabaiwuyu/DubboDemo​

参考资料:

​http://dubbo.apache.org/zh-cn/docs/user/preface/architecture.html​


标签:Dubbo,java,dubbo,jar,springframework,初识,beans,org
From: https://blog.51cto.com/u_13270529/5962445

相关文章

  • 如何基于 Spring Boot 快速开发一个 Dubbo 微服务应用
    Dubbo还提供了包括XML、API等多种启动与接入方式,更多开发方式和配置细节可参见配置手册。下载示例代码完整示例代码在dubbo-samples中。下载源码gitclone-bma......
  • 基于 Dubbo-Admin 实现根据请求条件路由
    Dubbo提供动态创建条件路由的服务治理能力,可以在无需重启应用的情况下,根据请求发起方、请求的方法条件路由。Dubbo可以通过XML配置,注解配置,动态配置实现动态根据请求条件路......
  • 基于 Dubbo-Admin 实现根据请求条件路由
    Dubbo提供动态创建条件路由的服务治理能力,可以在无需重启应用的情况下,根据请求发起方、请求的方法条件路由。Dubbo可以通过XML配置,注解配置,动态配置实现动态根据请求条件......
  • C语言学习初识day1
    全局变量,局部变量:      放在大括号里的变量就是局部变量;全局变量生命周期是整个程序。当局部变量和全局变量辆重名时,局部变量优先。常量,变量,常变量:C语言中的常量分......
  • Node.js(笔记01) - 初识Node.js
    本次学习目录:1)初识 Node.js2)fs 文件系统模块3)path 路径模块4)http 模块初识Node.js 回顾与思考1)前端需要掌握的基本技术:HTML、CSS和JAVASCRIPT2)浏览器中的 Javascri......
  • 基于 Dubbo Admin 实现流量灰度
    Dubbo提供流量灰度的服务治理能力,可以在无需重启应用的情况下,配置标签路由规则和条件路由实现灰度发布。Dubbo可以通过XML配置,注解配置,动态配置实现流量灰度,这里主要介绍......
  • Dubbo架构设计与源码解析(二) 服务注册
    一、Dubbo简介Dubbo是一款典型的高扩展、高性能、高可用的RPC微服务框架,用于解决微服务架构下的服务治理与通信问题。其核心模块包含【RPC通信】和【服务治理】,其中......
  • 初识Tomcat
    Tomcat学习归纳1.web认识:web服务器(主机)供浏览器访问的资源(静态资源,动态资源)2.学习JavaWeb开发,必须要先装WEB服务软件(Tomcat本质就是一个Java程序,但是这个Java......
  • 初识argparse 模块
    #1引入模块importargparse#2建立解析对象parser=argparse.ArgumentParser()#3增加属性:给xx实例增加一个aa属性#xx.add_argument("aa")parser.add_ar......
  • 4.Java程序初识
    4.Java程序初识4.1HelloWorld程序以Hello.java为例,java应用程序的执行入口是main()方法,其有固定格式:/***类文件,一个源文件最多只能有一个public类,且与文件名称一......