Dubbo + Zookeeper入门初探

2018年2月15日,阿里巴巴的dubbo进入了Apache孵化器,社区的加入,希望dubbo能变得更好…

Registry:注册中心,相当于房产中介,服务提供者和使用者都需要在这里注册/使用服务,
我使用 zookeeper 实现。

Monitor:监控中心,相当于房产局,它可以统计服务提供者和服务使用者的一些信息,及他们之间的关系,
我使用 dubbo admin 实现。

Provider:服务提供者,相当于房东,提供服务。

Consumer:服务消费者,想当于租户,使用服务。

通俗的解释下 dubbo 的整个流程,将服务比喻成房子:
start:dubbo 一启动,房东想好自己准备要租出去的房子
register:房东将房子拿到房产中介那边进行登记,并留下自己的联系方式
subscribe:租户告诉房产中介自己想租一个什么样的房子
notify:房产中介回复给租户符合条件的房子的房东的联系方式
invoke:租户拿着联系方式去找房东租房子
count:房产局全程监控着房东和租户之间的交易

start、register、subscribe 在 dubbo 服务一启动就完成了
notify、count 是异步执行的
invoke 是同步执行的

四、配置项目
<properties>
    <dubbo.version>2.6.1</dubbo.version>
    <zookeeper.version>3.5.2-alpha</zookeeper.version>
    <curator.version>4.0.1</curator.version>
</properties>
    
<!-- dubbo包 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <!-- 排除dubbo自带的spring和netty,使用项目的,如果本身项目没有,无需排除 -->
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>spring</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.jboss.netty</groupId>
            <artifactId>netty</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<!-- zookeeper包 -->
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <type>pom</type>
</dependency>
<!-- curator(zookeeper的客户端)包 -->
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-client</artifactId>
</dependency>
<dependency>
    <groupId>org.apache.curator</groupId>
    <artifactId>curator-framework</artifactId>
</dependency>

还需要在相关配置文件加上 dubbo 的 bean 的头部约束,将下面的添加到 bean 头部即可:
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"

http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd

4.1 服务提供方代码
import org.springframework.stereotype.Service;
@Service
public class TbItemServiceImpl extends ServiceImpl<TbItemMapper, TbItem> implements TbItemService {

}

需要修改 spring 关于 service 的配置文件,加入 dubbo 的配置信息:
<?xml version="1.0" encoding="UTF-8"?>
<beanshttp://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
	>

    <!-- 扫描service层注解 -->
    <context:component-scan base-package="jit.wxs.service"/>

    <!-- dubbo发布服务 -->
    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="e3-manager" />
    <!-- 配置zookeeper的地址,集群地址用逗号隔开 -->
    <dubbo:registry protocol="zookeeper" address="192.168.30.145:2181" />
    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />
    <!-- 声明需要暴露的服务接口
        ref:为注入的对应接口的bean
        timneout:超时时间,单位ms,开发模式可以设长一点方便debug
    -->
    <dubbo:service interface="jit.wxs.service.TbItemService" 
ref="tbItemServiceImpl" timeout="600000"/>
</beans>

dubbo:application:提供方的应用名
dubbo:registry:注册中心的类型和地址
dubbo:protocol:这个服务要暴露在哪个端口上(使用方根据这个端口使用服务)
dubbo:service:设置暴露的服务的接口,ref 为该接口的 bean,timeout 为超时时间

4.2 服务使用方代码
服务使用方,我使用 Spring MVC 来实现,修改 Spring MVC 的配置文件,加入 dubbo 的配置:
<?xml version="1.0" encoding="UTF-8"?>

<beans http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd"
>

    <!-- 扫描组件 -->
    <context:component-scan base-package="jit.wxs.web"/>

    <!-- 注解驱动 -->
    <mvc:annotation-driven />

    <!-- 全局异常类 -->
    <!--<bean class="cn.edu.jit.exception.GlobalExceptionResolver"/>-->

    <!-- 视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <!-- 引用dubbo服务 -->
    <!-- 使用方应用信息,用于计算依赖关系 -->
    <dubbo:application name="e3-manager-web"/>
    <!-- 指定zookeeper的地址,集群用逗号分隔 -->
    <dubbo:registry protocol="zookeeper" address="192.168.30.145:2181"/>
    <!-- 申明要访问的接口,并创建代理对象,注入bean,名为id的值 -->
    <dubbo:reference interface="jit.wxs.service.TbItemService" id="tbItemService" />
</beans>
dubbo:application: 使用方的应用名
dubbo:registry:注册中心的类型和地址
dubbo:reference:要使用的服务的接口,并将返回的注入 bean,名称为id设的值

如果配置没有问题的话,现在使用方已经能够使用提供方提供的服务了,直接将 tbItemService
注入进来即可:


@RestController
@RequestMapping("/items")
public class TbItemController {
    @Autowired
    private TbItemService tbItemService;

    @GetMapping("/{id}")
    public TbItem getItemById(@PathVariable Long id) {
        TbItem item = null;
        if(id != null) {
            item = tbItemService.selectById(id);
        }

        return item;
    }
}

dubbo和zookeeper项目中使用

服务的提供者将服务注册到注册中心,服务的消费者从注册中心获取服务,monitor监控服务的调用。
框架无非就是配置文件+java代码,所以dubbo也同理:
(1)首先看下B服务的提供者的配置文件和代码:
搭建b系统:
建立一个maven的war工程,导入依赖

<dependency>

        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>3.3.3</version>
      </dependency>
      <dependency>
        <groupId>com.github.sgroschupf</groupId>
        <artifactId>zkclient</artifactId>
        <version>0.1</version>
</dependency>
<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
            <exclusions>
                <exclusion>
                    <!-- 排除传递spring依赖 -->
                    <artifactId>spring</artifactId>
                    <groupId>org.springframework</groupId>
                </exclusion>
            </exclusions>
</dependency>

第二步:创建user对象:注意这里一定要实现序列化,并获取序列化的序号:
// 使用dubbo要求传输的对象必须实现序列化接口
public class User implements java.io.Serializable

创建服务接口和服务接口的实现类:

接口为了暴露服务的:
public interface UserService { 
    /**
     * 查询所有的用户数据
     *
     * @return
     */
    public List<User> queryAll(); 
}

5.3.6.  创建UserServiceImpl实现类
public class UserServiceImpl implements UserService {
 
    /**
     * 实现查询,这里做模拟实现,不做具体的数据库查询
     */
    public List<User> queryAll() {
        List<User> list = new ArrayList<User>();
        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setAge(10 + i);
            user.setId(Long.valueOf(i + 1));
            user.setPassword("123456");
            user.setUsername("username_" + i);
            list.add(user);
        }
        return list;
    }
 
}

下面就是dubbo的服务提供者的配置文件了:
实际项目中,相当于服务的提供者的第一步:编写配置文件
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd"
<!-- 提供方应用信息,用于计算依赖关系 -->
<dubbo:application name="dubbo-b-server" />
<!-- 这里使用的注册中心是zookeeper -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" client="zkclient"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocol name="dubbo" port="20880" />
<!-- 将该接口暴露到dubbo中 -->
<dubbo:service interface="cn.itcast.service.UserService" ref="userServiceImpl" />
<!-- 将具体的实现类加入到Spring容器中 -->
<bean id="userServiceImpl" class="cn.dubbo.service.impl.UserServiceImpl" /><br>

 这里spring与dubbo进行了无缝整合,所以这里进行了spring与dubbo的整合:

第二步:读取配置文件
我们需要在web.xml中将配置文件引入:
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:dubbo/dubbo-*.xml</param-value>
    </context-param>
    <!--Spring的ApplicationContext 载入 -->
<listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

第三步:配置服务消费者:
这里我们建立a的系统:
建立一个maven的jar工程:
导入依赖:
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.3</version>
            <exclusions>
                <exclusion>
                    <!-- 排除传递spring依赖 -->
                    <artifactId>spring</artifactId>
                    <groupId>org.springframework</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.3.3</version>
        </dependency>
 
        <dependency>
            <groupId>com.github.sgroschupf</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.1</version>
        </dependency>
    </dependencies>

从b系统拷贝:
1.1.1.   从b系统中拷贝User对象、UserService接口道a系统
服务的消费者配置:
dubbo-consumer.xml
    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:application name="dubbo-a-consumer" />
    <!-- 这里使用的注册中心是zookeeper -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" client="zkclient"/>
    <!-- 从注册中心中查找服务 -->
    <dubbo:reference id="userService" interface="cn.itcast.dubbo.service.UserService"/>

(1)导入dubbo、zookeeper依赖
(2)在服务提供者端,编写服务接口,服务接口的实现类,编写配置文件
(3)修改web.xml读取配置文件
(4)在服务消费者,即客户端,调用服务接口,调用服务实现类,编写配置文件







dubbo与zookeeper的关系

Dubbo建议使用Zookeeper作为服务的注册中心。
1.   Zookeeper的作用:
   zookeeper用来注册服务和进行负载均衡,哪一个服务由哪一个机器来提供必需让调用者知道,简单来说
就是ip地址和服务名称的对应关系。 zookeeper通过心跳机制可以检测挂掉的机器并将挂掉机器的ip和服务
对应关系从列表中删除。至于支持高并发,简单来说就是横向扩展,在不更改代码 的情况通过添加机器来
提高运算能力。通过添加新的机器向zookeeper注册服务,服务的提供者多了能服务的客户就多了。

2.  dubbo:

是管理中间层的工具,在业务层到数据仓库间有非常多服务的接入和服务提供者需要调度,dubbo提供一个
框架解决这个问题。
这个框架中要完成调度必须要有一个分布式的注册中心,储存所有服务的元数据,你可以用zk,也可以用别的,
只是大家都用zk。

3. zookeeper和dubbo的关系:
Dubbo的将注册中心进行抽象,是得它可以外接不同的存储媒介给注册中心提供服务,
有ZooKeeper,Memcached,Redis等。
引入了ZooKeeper作为存储媒介,也就把ZooKeeper的特性引进来。首先是负载均衡,单注册中心的承载能力
是有限的,在流量达到一定程度的时 候就需要分流,负载均衡就是为了分流而存在的,一个ZooKeeper群配合
相应的Web应用就可以很容易达到负载均衡;资源同步,单单有负载均衡还不 够,节点之间的数据和资源需要
同步,ZooKeeper集群就天然具备有这样的功能;

Dubbo(Dubbo与Zookeeper、SpringMVC整合)

第一步:在Linux上安装Zookeeper
Zookeeper作为Dubbo服务的注册中心,Dubbo原先基于数据库的注册中心,没采用Zookeeper,Zookeeper
一个分布式的服务框架,是树型的目录服务的数据存储,能做到集群管理数据 ,这里能很好的作为Dubbo服务
的注册中心,Dubbo能与Zookeeper做到集群部署,当提供者出现断电等异常停机时,Zookeeper注册中心能
自动删除提供者信息,当提供者重启时,能自动恢复注册数据,以及订阅请求。

(1)下载Zookeeper-3.4.6.tar.gz  地址http://www.apache.org/dist/zookeeper/
(2) 我们放到Linux下的一个文件夹,然后解压:
tar zxvf zookeeper-3.4.6.tar.gz
 clientPort:监听客户端连接的端口。
 tickTime:基本事件单元,以毫秒为单位。它用来控制心跳和超时,默认情况下最小的会话超时时间为
两倍的 tickTime。

 第二步:配置dubbo-admin的管理页面,方便我们管理页面
 (1)下载dubbo-admin-2.4.1.war包,在Linux的tomcat部署,先把dubbo-admin-2.4.1放在
tomcat的webapps/ROOT下,然后进行解压:
jar -xvf dubbo-admin-2.4.1.war
(2)然后到webapps/ROOT/WEB-INF下,有一个dubbo.properties文件,里面指向Zookeeper ,使用的
是
Zookeeper 的注册中心,如图所示:
 (3)然后启动tomcat服务,用户名和密码:root,并访问服务,显示登陆页面,说明dubbo-admin
部署成功,
如图所示:

第三步:SpringMVC与Dubbo的整合,这边使用的Maven的管理项目

第一:我们先开发服务注册的,就是提供服务,项目结构如图所示:
 (1)test-maven-api项目加入了一个服务接口,代码如下:
public interface TestRegistryService {  
    public String hello(String name);  
}

(2)test-maven-console在pom.xml加入Dubbo和Zookeeper的jar包、引用test-maven-api的jar包

(3)test-maven-console实现具体的服务,代码如下:
@Service("testRegistryService")  
public class TestRegistryServiceImpl implements TestRegistryService {  
 public String hello(String name) {    
    return "hello"+name;  
 } 
}

(4)我们服务以及实现好了,这时要暴露服务,代码如下:
 <!-- 提供方应用名称信息,这个相当于起一个名字,我们dubbo管理页面比较清晰是哪个应用
暴露出来的 -->  
<dubbo:application name="dubbo_provider"></dubbo:application>  
<!-- 使用zookeeper注册中心暴露服务地址 -->    
<dubbo:registry address="zookeeper://127.0.0.1:2181" check="false" 
subscribe="false" register=""></dubbo:registry>  
<!-- 要暴露的服务接口 -->    
<dubbo:service 
interface="cn.test.dubbo.registry.service.TestRegistryService" 
ref="testRegistryService" />        
 dubbo:registry 标签一些属性的说明:
 1)register是否向此注册中心注册服务,如果设为false,将只订阅,不注册。
 2)check注册中心不存在时,是否报错。
 3)subscribe是否向此注册中心订阅服务,如果设为false,将只注册,不订阅。
 4)timeout注册中心请求超时时间(毫秒)。
 5)address可以Zookeeper集群配置,地址可以多个以逗号隔开等。

dubbo:service标签的一些属性说明:
1)interface服务接口的路径
2)ref引用对应的实现类的Bean的ID
4)register 默认true ,该协议的服务是否注册到注册中心。
(5)启动项目,然后我们在Dubbo管理页面上显示,已经暴露的服务,但显示还没有消费者,因为我们还没
实现消费者服务,如图所示:

第二:我们在开发服务消费者,就是调用服务,我们在新建一个新的消费者项目结构如图所示:
1)test-maven-server-console的pom.xml引入Dubbo和Zookeeper的jar包、test-maven-api的jar包,
因为引入test-maven-api的jar包,我们在项目中调用像在本地调用一样。
 (2)test-maven-server-console项目的具体实现,代码如下:
 
 @Controller  
 public class IndexController {  
     @Autowired  
     private TestRegistryService testRegistryService;  
     @RequestMapping("/hello")  
    public String index(Model model){  
          String name=testRegistryService.hello("zz");  
          System.out.println("xx=="+name);  
        return "";  
    }  
}  

 (3)我们要引用的地址,代码如下:
   <dubbo:application name="dubbo_consumer"></dubbo:application>  
   <!-- 使用zookeeper注册中心暴露服务地址 -->    
   <dubbo:registry address="zookeeper://192.168.74.129:2181" check="false"></dubbo:registry>   
     <!-- 要引用的服务 -->    
   <dubbo:reference interface="cn.test.dubbo.registry.service.
TestRegistryService" id="testRegistryService"></dubbo:reference>  

说明:

   dubbo:reference 的一些属性的说明:

 1)interface调用的服务接口

 2)check 启动时检查提供者是否存在,true报错,false忽略

  3)registry 从指定注册中心注册获取服务列表,在多个注册中心时使用,值为<dubbo:registry>的
id属性,多个注册中心ID用逗号分隔

  4)loadbalance 负载均衡策略,可选值:random,roundrobin,leastactive,分别表示:随机,轮循,最少活跃调用

(4)项目启动,Dubbo管理页面,能看到消费者,

(5)然后访问消费者项目,Controller层能像调用本地一样调用服务的具体实现






猜你喜欢

转载自blog.csdn.net/Leon_Jinhai_Sun/article/details/87195559