dubbo这个框架相比大家都是知晓的。是一个rpc框架。
rpc是远程过程调用的意思。
调用的客户端调用远程的服务就像在调用自己本地的方法一样的方便。
通常情况下我们将dubbo服务搭建在另外一台机子上。通过rpc的方式让我们的程序去调用。
这样做没有问题。
但是这样做的话会存在一个问题。我们说网络连接是脆弱的。如果dubbo的服务断网了咋办。
那么这个时候我们的应用程序就会因为无法调用远程的服务,抛出一大堆异常。
所以这里引入zookeeper。zookeeper是一个搭建集群的框架。也就是说,我们多搭建几个dubbo服务。
来提高SOA的可靠性。
zookeeper为dubbo提供了一个注册的地方和一个心跳检测的机制。
注册也就是说,每个dubbo服务在zookeeper上注册一个ip,当我们的客户机去调用dubbo服务的时候,不是由我们客户机去手动指定调用那个dubbo服务。而是zookeeper帮我们决定去调用哪个zookeeper。
因为zookeeper知道那个dubbo服务是可用的。那些dubbo服务是关机掉了的。
所谓的心跳检测机制就是zookeeper维护一个定时任务,定时的去发起一个socket连接来确定这个dubbo服务是否可用。
好,说了一大堆,该上代码了,代码很简单,在这里笔者将代码的大体结构跟读者说明一下。
这里读者新建了两个工程。
分别是 dubboprovider和dubboconsumer
看名字就知道一个是dubbo的提供者。一个是dubbo的消费者。
我们先来看一个dubbo的提供者这个工程
SayHelloApi模块是我们dubbo提供者暴露出来的接口
sayHelloProvider和sayHelloProvider2两个模块分别模拟了两个dubbo服务。
用于体现zookeeper对多个dubbo服务的管理
至于dubboconsumer则相对就简单些。只需要去调用dubbo服务暴露出来的接口即可。
也就是 SayHelloApi那个模块
现在就先让我们将zookeeper先启动起来吧。
没有下载安装包的读者先到apache上去下载zookeeper的包
下载完成后解压掉,在conf文件夹下有一个zoo_sample.cfg文件,将其内容复制一份到zoo.cfg。
没有这个叫zoo.cfg这个文件的话zookeeper的启动会报错的。
接着我们来到bin目录,windows下点击zkServer.cmd linux下点击zkServer.sh
这样我们的zookeeper就启动起来了
我们这里先将maven的依赖说明一下吧。
<dependency>
<groupId>com.alibabagroupId>
<artifactId>dubboartifactId>
<version>2.5.4-SNAPSHOTversion>
dependency>
<dependency>
<groupId>com.101tecgroupId>
<artifactId>zkclientartifactId>
<version>0.10version>
dependency>
要加入dubbo和zookeeper的客户端连接的依赖。
以及其dubbo的服务的实现的模块还要依赖于暴露出来的接口即SayHelloApi。
依赖于暴露出来的接口的还有dubbo的客户。
所以呀SayHelloApi那个模块要使用maven的install命令一下,不然会找不到jar包报错的。
依赖讲清楚了。
接下来看具体实现。
我们先看暴露出来的api的那个模块里面是怎么写的。
很简单就是一个接口,其他的啥也不做。
package org.huluo;
public interface SayHello {
String sayHello();
}
我们在来看看接口的服务实现。
为了体现第一个dubbo服务和第二个dubbo服务的区别。所以这里我们这么写。
package org.huluo;
import com.alibaba.dubbo.config.annotation.Service;
@Service(version = "1.0.0")
public class SayHelloImpl implements SayHello {
public String sayHello() {
return "这是第一个dubbo提供的服务";
}
}
我们再来看看dubbo如何跟Spring集成来发布服务。
贴上配置文件
<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">
<dubbo:application name="hello-world-app" />
<dubbo:registry address="zookeeper://localhost:2181"/>
<dubbo:protocol name="dubbo" port="20880" />
<dubbo:service interface="org.huluo.SayHello" ref="sayHelloService" />
<bean id="sayHelloService" class="org.huluo.SayHelloImpl" />
beans>
至此第一个dubbo服务以及搭建完成。
第二个dubbo服务的搭建也是类似的。
package org.huluo;
import com.alibaba.dubbo.config.annotation.Service;
@Service(version = "1.0.0")
public class SayHelloImpl2 implements SayHello{
public String sayHello() {
return "这是第二个dubbo提供的服务";
}
}
<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">
<dubbo:application name="hello-world-app" />
<dubbo:registry address="zookeeper://localhost:2181"/>
<dubbo:protocol name="dubbo" port="20881" />
<dubbo:service interface="org.huluo.SayHello" ref="sayHelloService" />
<bean id="sayHelloService" class="org.huluo.SayHelloImpl2" />
beans>
最后我们将两个dubbo服务启动起来
package org.huluo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SayHelloImplTest {
public static void main(String[] args) throws InterruptedException {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:dubbo-provider.xml");
applicationContext.start();
while (true) {
}
}
}
package org.huluo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import static org.junit.Assert.*;
public class SayHelloImpl2Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:dubbo-provider2.xml");
applicationContext.start();
while (true) {
}
}
}
我们在来看看dubbo的调用方
package org.huluo;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DubboConsumer {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:dubbo-consumer.xml");
for (int i = 0; i < 100; i++) {
SayHello sayHello = (SayHello) applicationContext.getBean("sayHelloService");
System.out.println(sayHello.sayHello());
}
}
}
<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">
<dubbo:application name="dubbo_consumer"/>
<dubbo:registry address="zookeeper://localhost:2181"/>
<dubbo:reference id="sayHelloService" interface="org.huluo.SayHello" />
beans>
如果我们将第一个dubbo服务关闭掉。
那么打印的结果会显示全部调用的第二个dubbo服务,而不报错。
关闭掉第二个dubbo的服务也是一样的道理