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類,程序執行結果如下圖說明我們的程序正常執行了:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM