zookeeper+dubbo简单应用

一、dubbo是什么?

DUBBO是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,是阿里巴巴SOA服务化治理方案的核心框架。

二、dubbo的工作模式

 

节点角色说明:

  • Provider: 暴露服务的服务提供方。
  • Consumer: 调用远程服务的服务消费方。
  • Registry: 服务注册与发现的注册中心。
  • Monitor: 统计服务的调用次数和调用时间的监控中心。
  • Container: 服务运行容器。

调用关系说明:

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

 

三、一个简单的例子

1、首先我们需要安装Zookeeper,使用它作为dubbo的注册中心,Zookeeper可以单击部署、集群部署和伪集群部署(在一台服务器上配置多个Zookeeper实例);

1)在http://www.apache.org/dyn/closer.cgi/zookeeper/下载安装包,解压;

2)把conf目录下的zoo_sample.cfg文件修改为zoo.cfg,Zookeeper启动时会查找这个文件,配置信息:

# The number of milliseconds of each tick Zookeeper
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
#dataDir=/tmp/zookeeper
dataDir=D:\\dev-env\\zookeeper-3.5.1-alpha\\data
dataLogDir=D:\\dev-env\\zookeeper-3.5.1-alpha\\logs
# the port at which the clients will connect
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1

参数说明:

tickTime:服务器之间或客户端与服务器之间维持心跳的时间间隔,每一个tickTime时间会发送一个心跳
dataDir:数据目录,默认情况,zookeeper将写数据的日志也保存这个目录
dataLogDir:zookeeper保存日志文件的目录
clientPort:客户端连接zookeeper服务器的端口,zookeeper会监听这个端口,接受客户端的访问请求

Zookeeper的集群模式,需要增加几个配置项(也支持伪集群,在一台服务器上配置多个Zookeeper实例):

initLimit=5
syncLimit=2
server.1=192.168.2.1:2888:3888
server.2=192.168.2.2:2888:3888
initLimit: 这个是用来配置zookeeper接受客户端(这里说的客户端不是用户连接zookeeper的客户端,而是zookeeper服务器集群中连接到Leader的
Follower服务器)初始化连接时最长能忍受多少个心跳时间,当已经超过5个心跳时间长度后zookeeper服务器还没有收到客户端的返回信息,那么
表明这个客户端连接失败。总的时间长度就是5*2000=10秒
syncLimit: 这个配置标示Leader和Follower之间发送消息,请求和应答时间长度,最长不能超过多少个tickTime的时间长度,总的时间长度就是
2*2000=4秒
server.A=B:C:D 其中A是一个数字,表示这个是第几号服务器;B表示服务器ip地址,C表示这个服务器与集群中的Leader服务器交换信息的端口;
D表示万一集群中的Leader服务器挂了,需要一个端口来重新进行选举,选出一个新的Leader,而这个端口就是用来执行选举时服务器相互通信的端口。
如果是伪集群的配置方式,由于B都是一样的,所以不同的Zookeeper实例通信端口不能一样,所以要给他们分配不同的端口。
集群模式下,除了配置zoo.cfg文件,还需要配置一个myid,这个文件在dataDir目录下,这个文件里就有一个数据就是A的值,Zookeeper启动时会读取这个
文件,拿到里面的数据与zoo.cfg里面的配置信息比较从而判断到底是哪个server

3)然后就可以启动Zookeeper了,windows下运行bin\zkServer.cmd,linux下运行zkServer.sh。

注意:如果是在windows下安装Zookeeper,启动时可能会提示"Error: JAVA_HOME is incorrectly set." ,这时候我们需要修改bin目录下的zkEnv.cmd,修改如下:

原代码:

if not defined JAVA_HOME (
  echo Error: JAVA_HOME is not set.
  goto :eof
)

if not exist %JAVA_HOME%\bin\java.exe (
  echo Error: JAVA_HOME is incorrectly set.
  goto :eof
)

set JAVA=%JAVA_HOME%\bin\java

修改后:

if not defined JAVA_HOME (
  echo Error: JAVA_HOME is not set.
  goto :eof
)

if not exist "%JAVA_HOME%\bin\java.exe" (
  echo Error: JAVA_HOME is incorrectly set.
  goto :eof
)

set JAVA="%JAVA_HOME%\bin\java"

如果提示java版本问题,这时需要升级jdk。

2、下载dubbo-admin.war,修改一下WEB-INF/dubbo.properties中的配置,然后随便找个tomcat部署起来就行了;访问http://127.0.0.1:(你的端口号)/,这里可以对我们的dubbo服务进行管理。

3、编写一个简单的例子

项目使用Maven管理依赖。

1) 首先新建一个dubbo-parent项目,用来管理dubbo依赖:

pom中依赖配置如下:

<properties>
    <dubbo_version>2.1.2</dubbo_version>
    <spring_version>2.5.6.SEC03</spring_version>
    <javassist_version>3.15.0-GA</javassist_version>
    <log4j_version>1.2.16</log4j_version>
    <jcl_version>1.1</jcl_version>
    <netty_version>3.2.5.Final</netty_version>
    <zookeeper_version>3.3.3</zookeeper_version>
    <zkclient_version>0.1</zkclient_version>
</properties>
<dependencies>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>dubbo</artifactId>
        <version>${dubbo_version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.zookeeper</groupId>
        <artifactId>zookeeper</artifactId>
        <version>${zookeeper_version}</version>
    </dependency>
    <dependency>
        <groupId>com.github.sgroschupf</groupId>
        <artifactId>zkclient</artifactId>
        <version>${zkclient_version}</version>
    </dependency>
    <dependency>
        <groupId>org.javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>${javassist_version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring</artifactId>
        <version>${spring_version}</version>
    </dependency>
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j_version}</version>
    </dependency>
    <dependency>
        <groupId>commons-logging</groupId>
        <artifactId>commons-logging</artifactId>
        <version>${jcl_version}</version>
    </dependency>
    <dependency>
        <groupId>org.jboss.netty</groupId>
        <artifactId>netty</artifactId>
        <version>${netty_version}</version>
    </dependency>
</dependencies>

2)新建dubbo-api项目,我们在这个项目中定义服务接口:

建立一个接口DemoService:

package com.test.service;

public interface DemoService {

    String sayHello(String paramString);

}

3)新建dubbo-provider项目(生产者,服务提供方),继承dubbo-parent,同时配置依赖dubbo-api,pom如下:

<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>com.test.dubbo</groupId>
    <artifactId>dubbo-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>dubbo-provider</artifactId>

<dependencies>
    <dependency>
        <groupId>com.test.dubbo</groupId>
        <artifactId>dubbo-api</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

创建DemoService的实现DemoServiceImpl:

package com.test.service.impl;

import java.text.SimpleDateFormat;
import java.util.Date;

import com.alibaba.dubbo.rpc.RpcContext;
import com.test.service.DemoService;

public class DemoServiceImpl implements DemoService {

    @Override
    public String sayHello(String name) {
        System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello "
                + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
        return "Hello " + name + ", response from provider: "
                + RpcContext.getContext().getLocalAddress();
    }

}

创建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://code.alibabatech.com/schema/dubbo"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.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://127.0.0.1:2181" />
    
    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocol name="dubbo" port="20880" />
    
    <!-- 服务实现 -->
    <bean id="demoService" class="com.test.service.impl.DemoServiceImpl" />
    
    <!-- 声明需要暴露的服务 -->
    <dubbo:service interface="com.test.service.DemoService" ref="demoService" />
    
</beans>

创建程序启动类:

package com.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Provider {

    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] { "dubbo-provider.xml" });
        context.start();

        System.in.read(); // 按任意键退出
    }

}

4)新建dubbo-consumer项目(消费者,服务调用方),继承dubbo-parent,同时配置依赖dubbo-api,pom如下:

<modelVersion>4.0.0</modelVersion>
<parent>
    <groupId>com.test.dubbo</groupId>
    <artifactId>dubbo-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</parent>
<artifactId>dubbo-consumer</artifactId>

<dependencies>
    <dependency>
        <groupId>com.test.dubbo</groupId>
        <artifactId>dubbo-api</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
</dependencies>

创建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://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="consumer-of-helloworld-app"  />
 
    <!-- 注册中心,发现服务的地址 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />
 
    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="demoService" interface="com.test.service.DemoService" />
 
</beans>

创建启动类:

package com.test;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.test.service.DemoService;

public class Consumer {

    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
                new String[] { "dubbo-consumer.xml" });
        context.start();

        DemoService demoService = (DemoService) context.getBean("demoService"); // 获取远程服务代理
        String hello = demoService.sayHello("world"); // 执行远程方法
        System.out.println(hello);
    }
}

5)我们来测试一下!

首先运行dubbo-provider项目中Provider类:

然后我们在dubbo-admin的管理页面查看我们的服务是否已经在注册中心完成注册,如果程序正常执行,我们会看到如下界面:

接着,我们启动消费者dubbo-consumer项目中的Consumer类,程序执行结果如下图说明我们的程序正常执行了:

 

posted @ 2016-01-12 16:21  码农人生路  阅读(2896)  评论(0编辑  收藏  举报