zookeeper和dubbo入门教程

快速上手

分布式协调中间件:
类似于多线程环境中通过并发包来协调线程的访问控制
主要解决分布式环境中各个服务进程的访问控制问题

数据结构

结构化存储
树中的每个节点Znode,维护stat状态信息,包括数据变化的时间和版本等
每个Znode可以设置一个value值,只是管理和协调有关的数据
每个节点的数据都允许读和写
节点的创建必须按照层级创建
/node/node1/node1-1

特性

Znode在被创建的时候,指定节点类型,分类
1.持久化节点:节点的数据会持久化到硬盘
2.临时节点:节点的生命周期和创建该节点的客户端生命周期保持一致
一旦客户端会话结束,则该客户端所创建的临时节点会被自动删除
3.有序节点:在创建的节点后面会增加一个递增序列,该序列的同一级父节点之下时唯一的
注意:持久化和临时节点也可以设置为有序节点:持久化有序节点,临时有序节点
4.容器节点:当容器节点下的最后一个子节点被删除时,容器节点就会自动删除
5.TTL节点:针对持久化和持久化有序节点,设置存活时间
存活时间内该节点没有任何修改并且没有任何子节点,
就会被自动删除

watcher机制

针对Znode订阅通知机制,
Znode节点状态发生变化,或者Zookeeper客户端连接状态发生变化
触发事件通知
在服务注册与发现中,对服务调用者及时感知打服务提供者的变化,提供解决方案
Java Api提供了3种机制来针对Znode进行注册监听
1.getData():获取指定节点value信息,并且可以注册监听
2.getChildren():获取指定节点的所有子节点,并且允许注册监听
3.exists():判断节点是否存在,并且允许注册监听
上述3种方法,当监听的节点进行创建,修改,删除操作时,触发相应的事件通知
存在问题:watcher事件的触发都是一次性的
例如,客户端通过getData(‘/node’,true),注册监听
/node节点数据发生修改,客户端会收到修改事件通知
但是/node再次发生变化时,客户端无法收到watcher事件
解决:客户端在收到事件的回调中,再次注册事件

常见应用场景分析
分布式锁

Synchronized或者Lock解决:多线程环境下,共享资源的数据安全问题,处理级别:线程级别
锁的本质:排他性,避免统一时刻多个进程同时访问某一个共享资源
Zookeeper实现分布式锁:临时节点,以及同级节点的唯一性
1.获得锁过程
所有客户端去zookeeper服务器上/Exclusive_locks节点下创建一个临时节点/lock
基于同节点的唯一性.保证所有客户端中只有一个客户端能创建成功,获得排他锁
没有锁的客户端需要通过watcher机制监听/Exclusive_Lock节点下的子节点变更事件
监听/lock节点的变化情况以作出反应
2.释放锁过程
获得锁的客户端因为异常断开了和服务端的连接,临时节特性,/lock节点会自动被删除
获得锁客户端执行完成业务逻辑之后,主动删除创建/lock节点
当/lock节点被删除之后,zookeeper服务器再次通知所有监听了/Exclusive_Locks子节点变化的客户端,客户端收到通知后,再次发起创建/lock节点的操作来获得排他锁

master选举

2种方式
1.同一级节点不能重复创建一个已经存在的节点(排他锁)
假设集群有3个节点,需要选举出master
3个节点同时去zookeeper服务器上创建一个临时节点:/master-election
只能有1个客户端创建成功,创建成功的客户端所在机器就成了master
没有创建成功的客户端,针对该节点注册watcher事件,监控当前master机器是否存活
master节点挂了(/master-election节点被删除)
其他客户端重新发起选举master
2.临时节点有序性实现
所有参与选举的客户端在zookeeper服务器的/master节点下创建一个临时有序节点
编号最小为master
后续节点监听前一个节点的删除事件
例如:
client02监听client01
client01被删除,client02会收到修改事件通知,在回调事件中注册client02

dubbo集成zookeeper实现服务注册

问题:
1.服务动态上下线感知:
服务调用者要感知到服务提供者上下线的变化
2.负载均衡:
当服务提供者是由多个节点组成的集群环境时,
服务调用者需要通过负载均衡算法,来动态选择一台目标服务器进行远程通信

步骤

服务提供者添加zookeeper相关依赖

        
        <dependency>
            <groupId>org.apache.zookeepergroupId>
            <artifactId>zookeeperartifactId>
            <version>3.5.3-betaversion>
        dependency>

        <dependency>
            <groupId>org.apache.curatorgroupId>
            <artifactId>curator-frameworkartifactId>
            <version>4.0.1version>
        dependency>

        <dependency>
            <groupId>org.apache.curatorgroupId>
            <artifactId>curator-recipesartifactId>
            <version>4.0.1version>
        dependency>

修改application.yml文件
修改dubbo.registry.address地址为zookeeper服务器地址
表示当前dubbo服务需要注册到zookeeper上

dubbo:
 application:
   name: springboot-dubbo-provider
 protocol:
   name: dubbo
   port: 20880
 registry:
   address: zookeeper://your_ip:2181
注册中心实现原理

zookeeper和dubbo入门教程_第1张图片

当dubbo服务启动时,会去zookeeper服务器上
/dubbo/com.zyl.provider.service.IProviderService/providers(发布服务接口全路径名称)
目录下创建当前服务URL,providers:服务提供者类型
dubbo://ip:port该服务发布的协议,访问地址
URL是临时节点
优点:注册该节点的服务器下线了,这个服务URL地址就会从zookeeper服务器上被移除

dubbo服务消费者启动:
/dubbo/com.zyl.provider.IPoroviderService/providers节点下的子节点注册Watcher监听
可以感知到服务提供方节点的上下线变化
在/dubbo/com.zyl.provider.IProviderService/consumers写入自己URL
可以在监控平台上看到某个dubbo服务正在被哪些服务调用
如果dubbo消费者需要调用IProviderService服务
会去/dubbo/com.zyl.provider.IProviderService/providers路径下获取
所有该服务的提供方URL列表, 通过负载均衡算法计算出一个地址进行远程访问
服务注册/动态感知,用到:临时节点,持久化节点,watcher机制
还可以针对不同情况实现以下功能
1.基于临时节点的特性,当服务提供者宕机,注册中心自动删除该服务提供者提供的信息
2.注册中心重启,dubbo自动恢复注册数据及订阅请求
3.为了保证节点安全性,zookeeper提供ACL权限控制
在dubbo中,可以通过dubbo.registery.username/password设置节点验证信息
4.注册中心默认根节点是/dubbo
如果需要针对不同环境 设置不同的根节点,
使用dubbo.registry.group修改根节点名称

实战dubbo spring cloud

实现服务提供方

创建2个模块:spring-cloud-dubbo-sample-api/spring-cloud-dubbo-smaple-provider
服务提供者,存在api声明,服务调用者需要访问服务提供者声明的接口
推荐: 将服务接口打包发到私服上
父工程pom.xml锁定版本

    <properties>
        <maven.compiler.source>8maven.compiler.source>
        <maven.compiler.target>8maven.compiler.target>
        <project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
        <spring-cloud.version>Greenwich.SR2spring-cloud.version>
        <spring-cloud-alibaba.version>2.1.1.RELEASEspring-cloud-alibaba.version>
        <spring-boot.version>2.1.11.RELEASEspring-boot.version>
    properties>

    <dependencyManagement>
        <dependencies>

            <dependency>
                <groupId>org.springframework.cloudgroupId>
                <artifactId>spring-cloud-dependenciesartifactId>
                <version>${spring-cloud.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>

            <dependency>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-dependenciesartifactId>
                <version>${spring-boot.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>

            <dependency>
                <groupId>com.alibaba.cloudgroupId>
                <artifactId>spring-cloud-alibaba-dependenciesartifactId>
                <version>${spring-cloud-alibaba.version}version>
                <type>pomtype>
                <scope>importscope>
            dependency>

        dependencies>
    dependencyManagement>

spring-cloud-dubbo-sample-api声明接口,并发布到私服上

public interface IHelloService {
    String sayHello(String name);
}

服务提供者spring-cloud-dubbo-smaple-provider添加依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starterartifactId>
        dependency>

        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-dubboartifactId>
        dependency>

        <dependency>
            <groupId>com.zylgroupId>
            <artifactId>spring-cloud-dubbo-sample-apiartifactId>
            <version>1.0-SNAPSHOTversion>
        dependency>

        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-zookeeper-discoveryartifactId>
        dependency>

    dependencies>

创建接口实现类

@Service
public class IHelloServiceImpl implements IHelloService {

    @Value("${dubbo.application.name}")
    private String serverName;

    @Override
    public String sayHello(String name) {
        return "hello," + name + ", serverName:" + serverName;
    }
}

application.yml配置dubbo相关信息

dubbo:
  cloud:
    subscribed-services: dubbo-provider
spring:
  application:
    name: dubbo-consumer
  cloud:
    zookeeper:
      discovery:
        register: false
      connect-string: your-server:2181
server:
  port: 8081

在启动类声明@DubboComponentScan注解,启动服务
扫描注解所在包路径下@org.apache.dubbo.config.annotation.Service注解
,实现服务发布

@DubboComponentScan
@SpringBootApplication
public class DubboProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(DubboProviderApplication.class,args);
    }
}
dubbo服务提供方

spring-cloud-sample-dubbo-consumer
pom.xml依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starterartifactId>
        dependency>

        <dependency>
            <groupId>com.alibaba.cloudgroupId>
            <artifactId>spring-cloud-starter-dubboartifactId>
        dependency>

        <dependency>
            <groupId>com.zylgroupId>
            <artifactId>spring-cloud-dubbo-sample-apiartifactId>
            <version>1.0-SNAPSHOTversion>
        dependency>

        <dependency>
            <groupId>org.springframework.cloudgroupId>
            <artifactId>spring-cloud-starter-zookeeper-discoveryartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-webartifactId>
        dependency>
    dependencies>

application.yml添加dubbo配置信息

dubbo:
  cloud:
    subscribed-services: dubbo-provider
spring:
  application:
    name: dubbo-consumer
  cloud:
    zookeeper:
      discovery:
        register: false
      connect-string: your-ip:2181
server:
  port: 8081

spring.cloud.zookeeper.discovery.register=false,服务不需要注册到zookeeper上
dubbo.cloud.subscribed-services:服务调用者订阅服务提供方应用名称
如果有多个应用名称,使用’,‘分开
不推荐使用默认值:’*’
消费dubbo服务提供者IHelloService服务

@RestController
@RequestMapping("/consumer")
public class IHelloServiceImpl {

    @Reference
    private IHelloService helloService;

    @GetMapping("/say")
    public String say() {
        return helloService.sayHello("zyl");
    }
}

启动springBoot服务

@SpringBootApplication
public class DubboConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(DubboConsumerApplication.class,args);
    }
}

你可能感兴趣的:(zookeeper,dubbo,分布式)