Dubbo+Zookeeper

задняя часть сервер ZooKeeper Dubbo

строитьZooKeeperРеестр услуг

загрузить файлы:

zookeeper-3.4.9.tar.gz

распаковатьzookeeper-3.4.9.tar.gz

будет/opt/zookeeper-3.4.9/conf/zoo_sample.cfgкопировать как/opt/zookeeper-3.4.9/conf/zoo.cfg

Новый каталог:/opt/zookeeper-3.4.9/data

Исправлять/opt/zookeeper-3.4.9/conf/zoo.cfgдокумент

# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=/opt/zookeeper-3.4.9/data

запускатьZooKeeper:

[root@right bin]# pwd
/opt/zookeeper-3.4.9/bin
[root@right bin]# ./zkServer.sh start
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.9/bin/../conf/zoo.cfg
Starting zookeeper ... STARTED
[root@right bin]# ./zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/zookeeper-3.4.9/bin/../conf/zoo.cfg
Mode: standalone

Навсегда отключить брандмауэр:

chkconfig iptables off

Пример описания:

Создайте серверный проект:

Импорт зависимостей:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.soyoungboy.distribute</groupId>
    <artifactId>DubboConsumer</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <dependencies>
        <dependency>
            <groupId>com.soyoungboy.distribute</groupId>
            <artifactId>DubboInterfaces</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.5.6</version>
        </dependency>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.8</version>
        </dependency>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.10.RELEASE</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

Создайте класс, реализующий интерфейс службы.

import com.alibaba.dubbo.demo.DemoService;

public class DemoServiceImpl implements DemoService {

    public String sayHello(String name) {
        return "Hello " + name;
    }

}

Файл конфигурации Spring:

<?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="demo-provider"/>
    
    <!-- 配置注册中心的位置 -->
    <!-- Multicast 注册中心:multicast://224.5.6.7:1234 -->
    <!-- 配置ZooKeeper注册中心位置方式如下 -->
    <dubbo:registry address="192.168.159.200:2181" protocol="zookeeper"/>
    
    <!-- 配置Dubbo客户端的访问端口 -->
    <dubbo:protocol name="dubbo" port="20880"/>

    <!-- 配置接口实现类对应的bean -->    
    <bean id="demoService" class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>

    <!-- 配置提供的服务的接口 -->
    <dubbo:service interface="com.alibaba.dubbo.demo.DemoService" ref="demoService"/>

</beans>

 log4j.properties

log4j.rootLogger=DEBUG,myConsole
log4j.appender.myConsole=org.apache.log4j.ConsoleAppender
log4j.appender.myConsole.ImmediateFlush=true
log4j.appender.myConsole.Target=System.out
log4j.appender.myConsole.layout=org.apache.log4j.PatternLayout
log4j.appender.myConsole.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n

Создать клиентский проект: DubboConsumer

Импорт зависимостей:

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.6.8</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>dubbo</artifactId>
    <version>2.5.5</version>
</dependency>
<dependency>
    <groupId>com.101tec</groupId>
    <artifactId>zkclient</artifactId>
    <version>0.10</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>4.3.10.RELEASE</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>servlet-api</artifactId>
    <version>2.5</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jsp-api</artifactId>
    <version>2.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.soyoungboy.distributed</groupId>
    <artifactId>ServiceInterface</artifactId>
    <version>0.0.1-SNAPSHOT</version>
</dependency>

Конфигурационный файл:

<?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"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
    
    <!-- 配置当前应用模块名称 -->
    <dubbo:application name="demo-consumer"/>
    
    <!-- 配置注册中心位置 -->
    <dubbo:registry address="192.168.159.246:2181" protocol="zookeeper"/>
    
    <!-- 配置提供服务的接口类型 -->
    <dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService"/>
    
    <context:component-scan base-package="com.soyoungboy.distribute.handler"/>
    
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    
    <mvc:annotation-driven/>
    <mvc:default-servlet-handler/>

</beans>

при вызове службыbeanТип интерфейса введенияbean

import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.alibaba.dubbo.demo.DemoService;

@Controller
public class SayHelloHandler {
    
    @Autowired
    private DemoService demoService;
    
    @RequestMapping("/testSayHello")
    public String sayHello(Map<String, Object> map) {
        
        //像调用本地方法一样调用远程服务
        String sayHello = demoService.sayHello("Tom");
        
        map.put("result", sayHello);
        
        return "result";
    }

}

 

ZooKeeper

ZooKeeper=Файловая система+механизм уведомления

 

Файловая система: ZooKeeperУправляйте данными с помощью древовидной структуры. И с "/«Как корневой узел древовидной структуры.

Механизм уведомления:использоватьZooKeeperПосле механизма уведомления каждый модуль работает в определенномznode установлен наWatcher(Observer) для отслеживания изменений значений на текущем узле. однаждыWatcher При обнаружении изменения данных проект модуля будет немедленно уведомлен, чтобы автоматически реализовать эффект «одна модификация, действующая везде».

Общие команды:

 

启动服务器:./zkServer.sh start
停止服务器:./zkServer.sh stop
启动客户端:./zkCli.sh
退出客户端:[zk: localhost:2181(CONNECTED) 6] quit
ls:查看当前znode中所包含的内容
ls2:查看当前节点数据并能看到更新次数等数据
stat:查看节点状态 stat /tebieshuai
set:设置节点的具体值
set 节点 value值 set /tebieshuai new_value
get:获得节点的值 get /shuai
get节点
delete:可以删除指定znode,当该znode拥有子znode时,必须先删除其所有子znode,否则操作将失败。
rmr:命令可用于代替delete命令,rmr是一个递归删除命令,如果发生指定节点拥有子节点时,rmr命令会首先删除子节点。
rmr /chou000000008
create:
create [-s] [-e] path data acl
普通创建:不带有-s、-e参数
-s:含有序列 create -s /chou true
-e:临时(重启或者超时消失)create -s -e /templ uuu

Содержание атрибута Stat:

czxid: причина этогоznodeсозданныйzxid , транзакция, которая создала узелzxid(ZooKeeper Transaction Id )

ctime:znodeсоздано за миллисекунды( от1970В начале)

mzxid:znodeпоследнее обновлениеzxid

mtime:znodeПоследние измененные миллисекунды( от1970год начала)

pZxid:znodeПоследние обновленные детские узлыzxid

cversion:znodeномер изменения дочернего узла,znode Время модификации подузла

dataversion:znodeномер изменения данных

aclVersion:znodeИзменить номер списка контроля доступа

ephemeralOwner: Если это временный узел, этоznodeвладелецsession id . Да, если не эфемерный узел0.

dataLength:znodeдлина данных

numChildren:znodeКоличество дочерних узлов

Команда ZooKeeper из четырех слов:

ruok: Проверьте, находится ли служба в правильном состоянии. Если это так, служба возвращает «imok», в противном случае ответа нет.
stat: вывести список производительности и подключенных клиентов
conf: вывод сведений о соответствующей конфигурации службы
минусы: перечисляет полные сведения о соединении/сеансе для всех клиентов, подключенных к серверу. Включите такую ​​информацию, как количество пакетов, «полученных/отправленных», идентификатор сеанса, задержка операции, последняя выполненная операция и т. д.
dump: список необработанных сеансов и эфемерных узлов.
envi: вывод подробной информации о сервисной среде (отличается от команды conf)
reqs: Список необработанных запросов
wchs: список сведений о просмотре сервера
wchc: список сведений о наблюдении за сервером по сеансам, его вывод представляет собой список сеансов, связанных с просмотром.
wchp: список серверов по пути Детали часов. Он выводит путь, связанный с сеансом

Операция Zookeeper через Java-программу

Информация о зависимости:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.soyoungboy.zookeeper</groupId>
    <artifactId>ZooKeeper</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <dependencies>
        <dependency>
            <groupId>com.101tec</groupId>
            <artifactId>zkclient</artifactId>
            <version>0.10</version>
        </dependency>
        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.9</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.9</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

Код действия Java:

import java.io.IOException;
import java.util.ArrayList;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
import org.apache.zookeeper.data.Stat;

public class NodeOperation {
    
    /**
     * 设置节点值
     * @param zooKeeper
     * @param path
     * @param nodeData
     * @return
     * @throws KeeperException
     * @throws InterruptedException
     */
    public Stat setNodeData(ZooKeeper zooKeeper, String path, String nodeData) throws KeeperException, InterruptedException {
        
        Stat stat = zooKeeper.setData(path, nodeData.getBytes(), -1);
        return stat;
    }
    
    /**
     * 获取指定节点上的数据
     * @param zooKeeper
     * @param path
     * @return
     * @throws KeeperException
     * @throws InterruptedException
     */
    public String getNodeData(ZooKeeper zooKeeper, String path) throws KeeperException, InterruptedException {
        
        byte[] data = zooKeeper.getData(path, false, new Stat());
        
        return new String(data);
    }
    
    /**
     * 创建节点
     * @param zooKeeper ZooKeeper服务器连接对象
     * @param path 要创建的节点的路径
     * @param nodeData 节点的数据
     * @return
     * @throws KeeperException
     * @throws InterruptedException
     */
    public String createNewNode(ZooKeeper zooKeeper, String path, String nodeData) throws KeeperException, InterruptedException {
        
        //将字符串类型的数据转换为字节数组类型
        byte[] nodeDataBytes = nodeData.getBytes();
        
        //访问控制列表
        ArrayList<ACL> openAclUnsafe = Ids.OPEN_ACL_UNSAFE;
        
        //创建模式
        CreateMode mode = CreateMode.PERSISTENT;
        
        //执行创建
        String result = zooKeeper.create(path, nodeDataBytes, openAclUnsafe, mode);
        
        return result;
        
    }
    
    /**
     * 连接ZooKeeper服务器
     * @return
     * @throws IOException
     */
    public ZooKeeper connectToZookeeper() throws IOException {
        
        //连接ZooKeeper服务器的信息
        String connectString = "192.168.159.200:2181";
        int sessionTimeout = 50 * 1000;
        
        //创建ZooKeeper对象
        ZooKeeper zooKeeper = new ZooKeeper(connectString, sessionTimeout, new Watcher() {
            
            @Override
            public void process(WatchedEvent event) {
                //暂时不做任何处理
            }
        });
        
        return zooKeeper;
    }

}

Протестируйте с помощью кода:

import java.io.IOException;

import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.junit.Test;

import com.atguigu.zookeeper.NodeOperation;

public class ZooKeeperTest {
    
    private NodeOperation nodeOperation = new NodeOperation();
    private ZooKeeper zooKeeper = null;
    
    @Test
    public void testSetNodeData() throws KeeperException, InterruptedException {
        Stat stat = nodeOperation.setNodeData(
                zooKeeper, "/shuai", "are you ok");
        System.out.println(stat);
        int cversion = stat.getCversion();
        System.out.println(cversion);
    }
    
    @Test
    public void testGetNodeData() throws KeeperException, InterruptedException {
        String nodeData = nodeOperation.getNodeData(zooKeeper, "/shuai");
        System.out.println(nodeData);
    }
    
    @Test
    public void testCreateNode() throws KeeperException, InterruptedException {
        
        //create /aaa com.atguigu.service
        
        String path = "/aaa";
        String nodeData = "com.atguigu.service";
        
        String result = nodeOperation.createNewNode(zooKeeper, path, nodeData);
        System.out.println(result);
        
    }
    
    {
        try {
            zooKeeper = nodeOperation.connectToZookeeper();
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }
    
    @Test
    public void testConnection() throws IOException, InterruptedException {
        ZooKeeper zooKeeper = nodeOperation.connectToZookeeper();
        System.out.println(zooKeeper);
        Thread.sleep(Long.MAX_VALUE);
    }

}

механизм уведомления

 Реализуйте непрерывное наблюдение, используя рекурсивный вызов методов

 

Код:

public class MyWatchMulti {
    
    public static void main(String[] args) throws IOException, KeeperException, InterruptedException {
        
        final ZooKeeper zooKeeper = new ZooKeeper("192.168.159.200:2181", 50 * 1000, new Watcher() {
            @Override
            public void process(WatchedEvent event) {}
        });
        
        byte[] nodeData = zooKeeper.getData("/notify", new Watcher() {
            
            //回调:由系统或其他对象调用我们写的方法,而不是像平时我们自己调用自己写的方法
            public void process(WatchedEvent event) {
                System.err.println("*********接收到通知了[第一次]***********");
                
                MyWatchMulti multi = new MyWatchMulti();
                
                //调用递归方法持续观察
                String currentValue = multi.recursionGetData(zooKeeper);
                System.err.println("当前值="+currentValue);
                
                System.err.println("*********接收到通知了[第一次]***********");
            }
        }, new Stat());
        
        System.out.println(new String(nodeData));
        
        Thread.sleep(Long.MAX_VALUE);
        
    }
    
    /**
     * 以递归方式执行获取数据和设置观察者操作实现持续观察
     * @param zooKeeper
     * @return
     */
    public String recursionGetData(final ZooKeeper zooKeeper) {
        byte[] currentValue = null;
        try {
            currentValue = zooKeeper.getData("/notify", new Watcher() {
                
                @Override
                public void process(WatchedEvent event) {
                    
                    //递归调用的核心
                    recursionGetData(zooKeeper);
                }
            }, new Stat());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
        
        String currentResult = new String(currentValue);
        System.out.println("递归中获取的值="+currentResult);
        
        return currentResult;
    }

}

 

Категории