├── README.md
├── pom.xml
└── src
└── main
├── java
├── dubbo
│ └── helloworld
│ │ ├── ConsumerAction.java
│ │ ├── DemoService.java
│ │ ├── DemoServiceImpl.java
│ │ └── StartProvider.java
├── kafka
│ └── helloWorld
│ │ ├── Consumer.java
│ │ ├── KafkaProperties.java
│ │ └── Produce.java
└── zookeeper
│ ├── CreateGroup
│ ├── ConnectionWatcher.java
│ ├── CreateGroup.java
│ └── CreateGroupTest.java
│ ├── DeleteGroup
│ ├── DeleteGroup.java
│ └── DeleteGroupTest.java
│ ├── DistributedLock
│ └── DistributedLock.java
│ ├── DistributedQueue
│ └── DistributedQueue.java
│ └── HelloWorld.java
└── resources
└── helloDubbo
├── consumer.xml
└── provider.xml
/README.md:
--------------------------------------------------------------------------------
1 | # Java分布式应用学习笔记
2 | 代码目录结构
3 | ------
4 | * zookeeper
5 | * dubbo
6 | * kafka
7 |
8 | 笔记详情
9 | ------
10 | * [知乎专栏 - 编程之路](https://zhuanlan.zhihu.com/coding4fun)
11 | * [分布式学习(1) ---- 初识Zookeeper](https://zhuanlan.zhihu.com/p/24996631)
12 | * [分布式学习(2) ---- Zookeeper实现分布式锁](https://zhuanlan.zhihu.com/p/25010779)
13 | * [分布式学习(3) ---- 初识Nginx](https://zhuanlan.zhihu.com/p/25102281)
14 | * [分布式学习(4) ---- Spring Session + Redis实现分布式Session共享](https://zhuanlan.zhihu.com/p/25010950)
15 | * [分布式学习(5) ---- 初识消息系统kafka](https://zhuanlan.zhihu.com/p/25212966)
16 | * [分布式学习(6) ---- 深入kafka生产消费模型](https://zhuanlan.zhihu.com/p/25227580)
17 | * [分布式学习(7) ---- 常见web攻防简易总结](https://zhuanlan.zhihu.com/p/25249464)
18 | * [分布式学习(8) ---- 分布式网站优化简易总结](https://zhuanlan.zhihu.com/p/25324226)
19 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | zookeeper-dubbo
8 | zookeeper-dubbo
9 | 1.0-SNAPSHOT
10 |
11 |
12 |
13 | org.apache.maven.plugins
14 | maven-compiler-plugin
15 |
16 | 1.7
17 | 1.7
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | org.apache.zookeeper
28 | zookeeper
29 | 3.4.9
30 |
31 |
32 | com.101tec
33 | zkclient
34 | 0.10
35 |
36 |
37 |
38 |
39 | com.alibaba
40 | dubbo
41 | 2.4.9
42 |
43 |
44 |
45 | org.springframework
46 | spring-context
47 | 3.2.8.RELEASE
48 | runtime
49 |
50 |
51 |
52 | junit
53 | junit
54 | 4.11
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/src/main/java/dubbo/helloworld/ConsumerAction.java:
--------------------------------------------------------------------------------
1 | package dubbo.helloworld;
2 |
3 | import org.springframework.context.support.ClassPathXmlApplicationContext;
4 |
5 | /**
6 | * 消费者消费服务
7 | */
8 | public class ConsumerAction {
9 | public static void main(String[] args) {
10 | ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/helloDubbo/consumer.xml");
11 | DemoService demoService = (DemoService) context.getBean("demoService"); // 获取远程服务代理
12 | String hello = demoService.sayHello("KKys!"); // 执行远程方法
13 | System.out.println(hello); // 显示调用结果
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/dubbo/helloworld/DemoService.java:
--------------------------------------------------------------------------------
1 | package dubbo.helloworld;
2 |
3 | /**
4 | * 定义服务接口: (该接口需单独打包,在服务提供方和消费方共享)
5 | */
6 | public interface DemoService {
7 | String sayHello(String name);
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/dubbo/helloworld/DemoServiceImpl.java:
--------------------------------------------------------------------------------
1 | package dubbo.helloworld;
2 |
3 | /**
4 | * 在服务提供方实现接口:(对服务消费方隐藏实现)
5 | */
6 | public class DemoServiceImpl implements DemoService {
7 | @Override
8 | public String sayHello(String name) {
9 | return "Hello dubbo : " + name;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/dubbo/helloworld/StartProvider.java:
--------------------------------------------------------------------------------
1 | package dubbo.helloworld;
2 |
3 | import org.springframework.context.support.ClassPathXmlApplicationContext;
4 |
5 | import java.io.IOException;
6 |
7 | /**
8 | * 启动服务提供方
9 | */
10 | public class StartProvider {
11 | public static void main(String[] args) throws IOException {
12 | System.out.println("启动");
13 | ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/helloDubbo/provider.xml");
14 | context.start();
15 | System.in.read(); // 按任意键退出
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/kafka/helloWorld/Consumer.java:
--------------------------------------------------------------------------------
1 | package kafka.helloWorld;
2 |
3 | import org.apache.kafka.clients.consumer.ConsumerRecord;
4 | import org.apache.kafka.clients.consumer.ConsumerRecords;
5 | import org.apache.kafka.clients.consumer.KafkaConsumer;
6 | import org.apache.kafka.common.TopicPartition;
7 |
8 | import java.util.*;
9 |
10 |
11 | /**
12 | * kafka消费者
13 | * Created by yaosheng on 2017/2/9.
14 | */
15 |
16 |
17 | public class Consumer{
18 |
19 | public static void main(String[] args) {
20 | Properties props = new Properties();
21 | props.put("bootstrap.servers", "121.42.8.85:9092");
22 | props.put("group.id", "test");
23 | props.put("enable.auto.commit", "true");
24 | props.put("auto.commit.interval.ms", "1000");
25 | props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
26 | props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
27 | KafkaConsumer consumer = new KafkaConsumer<>(props);
28 | consumer.subscribe(Arrays.asList("test2"));
29 | while (true) {
30 | ConsumerRecords records = consumer.poll(100);
31 | for (ConsumerRecord record : records)
32 | System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/kafka/helloWorld/KafkaProperties.java:
--------------------------------------------------------------------------------
1 | package kafka.helloWorld;
2 |
3 | /**
4 | * Created by yaosheng on 2017/2/9.
5 | */
6 | public interface KafkaProperties {
7 | final static String zkConnect = "121.42.8.85:2181,121.42.8.85:2182,121.42.8.85:2183";
8 | final static String groupId = "group1";
9 | final static String topic = "topic1";
10 | final static String kafkaServer = "121.42.8.85:9092,121.42.8.85:9092,121.42.8.85:9092";
11 | final static int kafkaProducerBufferSize = 64 * 1024;
12 | final static int connectionTimeOut = 20000;
13 | final static int reconnectInterval = 10000;
14 | final static String topic2 = "topic2";
15 | final static String topic3 = "topic3";
16 | final static String clientId = "SimpleConsumerDemoClient";
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/kafka/helloWorld/Produce.java:
--------------------------------------------------------------------------------
1 | package kafka.helloWorld;
2 | import org.apache.kafka.clients.producer.KafkaProducer;
3 | import org.apache.kafka.clients.producer.ProducerRecord;
4 | import org.apache.kafka.clients.producer.Producer;
5 | import java.util.Properties;
6 |
7 |
8 |
9 | /**
10 | * kafka生产者
11 | * Created by yaosheng on 2017/2/9.
12 | */
13 |
14 | public class Produce {
15 |
16 | public static void main(String[] args) {
17 | System.out.println("begin produce");
18 | connectionKafka();
19 | System.out.println("finish produce");
20 | }
21 |
22 | public static void connectionKafka() {
23 | Properties props = new Properties();
24 | props.put("bootstrap.servers", "121.42.8.85:9092");
25 | //ack是判别请求是否为完整的条件(就是是判断是不是成功发送了)。我们指定了“all”将会阻塞消息,这种设置性能最低,但是是最可靠的。
26 | //props.put("acks", "all");
27 | //失败后重试次数
28 | props.put("retries", 0);
29 | //默认缓冲可立即发送,即遍缓冲空间还没有满,但是,如果你想减少请求的数量,可以设置linger.ms大于0,就把消息先加到缓存队列中,稍后一同发出
30 | //props.put("linger.ms", 1);
31 | //缓存未发送消息的大小
32 | props.put("batch.size", 16384);
33 | //控制生产者可用的缓存总量
34 | props.put("buffer.memory", 33554432);
35 | props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
36 | props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
37 |
38 | Producer producer = new KafkaProducer<>(props);
39 | for (int i = 0; i < 10; i++) {
40 | producer.send(new ProducerRecord("test2", Integer.toString(i), Integer.toString(i)));
41 | System.out.println("send成功");
42 | try {
43 | //两秒发一次
44 | Thread.currentThread().sleep(2000);
45 | } catch (InterruptedException e) {
46 | e.printStackTrace();
47 | }
48 | }
49 | producer.close();
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/zookeeper/CreateGroup/ConnectionWatcher.java:
--------------------------------------------------------------------------------
1 | package zookeeper.CreateGroup;
2 |
3 | import org.apache.zookeeper.WatchedEvent;
4 | import org.apache.zookeeper.Watcher;
5 | import org.apache.zookeeper.ZooKeeper;
6 |
7 | import java.io.IOException;
8 | import java.util.concurrent.CountDownLatch;
9 |
10 | /**
11 | * 连接的观察者,封装了zk的创建等
12 | * Created by yaosheng on 2017/1/17.
13 | *
14 | */
15 | public class ConnectionWatcher implements Watcher {
16 | private static final int SESSION_TIMEOUT = 5000;
17 |
18 | protected ZooKeeper zk = null;
19 | private CountDownLatch countDownLatch = new CountDownLatch(1);
20 |
21 | public void process(WatchedEvent event) {
22 | Event.KeeperState state = event.getState();
23 |
24 | if(state == Event.KeeperState.SyncConnected){
25 | countDownLatch.countDown();
26 | }
27 | }
28 |
29 | /**
30 | * 连接资源
31 | * @param hosts
32 | * @throws IOException
33 | * @throws InterruptedException
34 | */
35 | public void connection(String hosts) throws IOException, InterruptedException {
36 | zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this);
37 | countDownLatch.await();
38 | }
39 |
40 | /**
41 | * 释放资源
42 | * @throws InterruptedException
43 | */
44 | public void close() throws InterruptedException {
45 | if (null != zk) {
46 | try {
47 | zk.close();
48 | } catch (InterruptedException e) {
49 | throw e;
50 | }finally{
51 | zk = null;
52 | System.gc();
53 | }
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/src/main/java/zookeeper/CreateGroup/CreateGroup.java:
--------------------------------------------------------------------------------
1 | package zookeeper.CreateGroup;
2 |
3 | import org.apache.zookeeper.*;
4 |
5 | import java.io.IOException;
6 | import java.util.concurrent.CountDownLatch;
7 |
8 | /**
9 | * Created by yaosheng on 2017/1/16.
10 | */
11 |
12 | public class CreateGroup implements Watcher{
13 |
14 | private static final int SESSION_TIMEOUT = 1000;//会话延时
15 |
16 | private ZooKeeper zk = null;
17 |
18 | private CountDownLatch countDownLatch = new CountDownLatch(1);//同步计数器
19 |
20 |
21 | /**
22 | * 这里我们使用了同步计数器CountDownLatch,在connect方法中创建执行了zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this);之后,
23 | * 下边接着调用了CountDownLatch对象的await方法阻塞,因为这是zk客户端不一定已经完成了与服务端的连接,在客户端连接到服务端时会触发观察者调用process()方法,
24 | * 我们在方法里边判断一下触发事件的类型,完成连接后计数器减一,connect方法中解除阻塞。
25 | 还有两个地方需要注意:这里创建的znode的访问权限是open的,且该znode是持久化存储的。
26 | *
27 | */
28 | @Override
29 | public void process(WatchedEvent event) {
30 | if(event.getState() == Event.KeeperState.SyncConnected){
31 | countDownLatch.countDown();//计数器减一
32 | }
33 | }
34 |
35 | /**
36 | * 创建zk对象
37 | * 当客户端连接上zookeeper时会执行process(event)里的countDownLatch.countDown(),计数器的值变为0,则countDownLatch.await()方法返回。
38 | * @param hosts
39 | * @throws IOException
40 | * @throws InterruptedException
41 | */
42 | public void connect(String hosts) throws IOException, InterruptedException {
43 | zk = new ZooKeeper(hosts, SESSION_TIMEOUT, this);
44 | countDownLatch.await();//阻塞程序继续执行
45 | }
46 |
47 | /**
48 | * 创建group
49 | *
50 | * @param groupName 组名
51 | * @throws KeeperException
52 | * @throws InterruptedException
53 | */
54 | public void create(String groupName) throws KeeperException, InterruptedException {
55 | String path = "/" + groupName;
56 | String createPath = zk.create(path, null, ZooDefs.Ids.OPEN_ACL_UNSAFE/*允许任何客户端对该znode进行读写*/, CreateMode.PERSISTENT/*持久化的znode*/);
57 | System.out.println("Created " + createPath);
58 | }
59 |
60 | /**
61 | * 关闭zk
62 | * @throws InterruptedException
63 | */
64 | public void close() throws InterruptedException {
65 | if(zk != null){
66 | try {
67 | zk.close();
68 | } catch (InterruptedException e) {
69 | throw e;
70 | }finally{
71 | zk = null;
72 | System.gc();
73 | }
74 | }
75 | }
76 |
77 | public static void main(String[] args){
78 |
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/zookeeper/CreateGroup/CreateGroupTest.java:
--------------------------------------------------------------------------------
1 | package zookeeper.CreateGroup;
2 |
3 | import org.apache.zookeeper.KeeperException;
4 | import org.junit.After;
5 | import org.junit.Before;
6 | import org.junit.Test;
7 |
8 | import java.io.IOException;
9 |
10 | /**
11 | * Created by yaosheng on 2017/1/16.
12 | */
13 | public class CreateGroupTest {
14 | private static String hosts = "xxx:2181";
15 | private static String groupName = "zoo";
16 |
17 | private CreateGroup createGroup = null;
18 | /**
19 | * init
20 | * @throws InterruptedException
21 | * @throws KeeperException
22 | * @throws IOException
23 | */
24 | @Before
25 | public void init() throws KeeperException, InterruptedException, IOException {
26 | createGroup = new CreateGroup();
27 | createGroup.connect(hosts);
28 | }
29 |
30 | @Test
31 | public void testCreateGroup() throws KeeperException, InterruptedException {
32 | createGroup.create(groupName);
33 | }
34 |
35 | /**
36 | * 销毁资源
37 | */
38 | @After
39 | public void destroy() {
40 | try {
41 | createGroup.close();
42 | createGroup = null;
43 | System.gc();
44 | } catch (InterruptedException e) {
45 | e.printStackTrace();
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/zookeeper/DeleteGroup/DeleteGroup.java:
--------------------------------------------------------------------------------
1 | package zookeeper.DeleteGroup;
2 |
3 | import org.apache.zookeeper.KeeperException;
4 | import zookeeper.CreateGroup.ConnectionWatcher;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * Created by yaosheng on 2017/1/17.
10 | * zk.delete(path,version)方法的第二个参数是znode版本号,如果提供的版本号和znode版本号一致才会删除这个znode,
11 | * 这样可以检测出对znode的修改冲突。通过将版本号设置为-1,可以绕过这个版本检测机制,无论znode的版本号是什么,都会直接将其删除。
12 | */
13 | public class DeleteGroup extends ConnectionWatcher {
14 | public void delete(String groupName) {
15 | String path = "/" + groupName;
16 |
17 | try {
18 | List children = zk.getChildren(path, false);
19 |
20 | for(String child : children){
21 | zk.delete(path + "/" + child, -1);
22 | }
23 | zk.delete(path, -1);//版本号为-1,
24 | } catch (KeeperException e) {
25 | e.printStackTrace();
26 | } catch (InterruptedException e) {
27 | e.printStackTrace();
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/zookeeper/DeleteGroup/DeleteGroupTest.java:
--------------------------------------------------------------------------------
1 | package zookeeper.DeleteGroup;
2 |
3 | import org.apache.zookeeper.KeeperException;
4 | import org.junit.After;
5 | import org.junit.Before;
6 | import org.junit.Test;
7 |
8 | import java.io.IOException;
9 |
10 | /**
11 | * Created by yaosheng on 2017/1/17.
12 | */
13 | public class DeleteGroupTest {
14 | private static final String HOSTS = "xxx:2181";
15 | private static final String groupName = "zoo";
16 |
17 | private DeleteGroup deleteGroup = null;
18 |
19 | @Before
20 | public void init() throws IOException, InterruptedException {
21 | deleteGroup = new DeleteGroup();
22 | deleteGroup.connection(HOSTS);
23 | }
24 |
25 | @Test
26 | public void testDelete() throws IOException, InterruptedException, KeeperException {
27 | deleteGroup.delete(groupName);
28 | }
29 |
30 | @After
31 | public void destroy() throws InterruptedException {
32 | if(null != deleteGroup){
33 | try {
34 | deleteGroup.close();
35 | } catch (InterruptedException e) {
36 | throw e;
37 | }finally{
38 | deleteGroup = null;
39 | System.gc();
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/zookeeper/DistributedLock/DistributedLock.java:
--------------------------------------------------------------------------------
1 | package zookeeper.DistributedLock;
2 |
3 | import org.apache.zookeeper.*;
4 | import org.apache.zookeeper.data.Stat;
5 |
6 | import java.io.IOException;
7 | import java.util.Collections;
8 | import java.util.List;
9 | import java.util.concurrent.CountDownLatch;
10 |
11 | /**
12 | * zookeeper实现分布式锁
13 | */
14 | public class DistributedLock implements Watcher{
15 | private int threadId;
16 | private ZooKeeper zk = null;
17 | private String selfPath;
18 | private String waitPath;
19 | private String PREFIX_OF_THREAD;
20 | private static final int SESSION_TIMEOUT = 10000;
21 | private static final String GROUP_PATH = "/lock";
22 | private static final String SUB_PATH = "/lock/sub";
23 | private static final String CONNECTION_STRING = "xxx:2181";
24 |
25 | private static final int THREAD_NUM = 10;
26 | //确保连接zk成功;
27 | private CountDownLatch connectedSemaphore = new CountDownLatch(1);
28 | //确保所有线程运行结束;
29 | private static final CountDownLatch threadSemaphore = new CountDownLatch(THREAD_NUM);
30 | public DistributedLock(int id) {
31 | this.threadId = id;
32 | PREFIX_OF_THREAD = "【第"+threadId+"个线程】";
33 | }
34 | public static void main(String[] args) {
35 | for(int i=0; i < THREAD_NUM; i++){
36 | final int threadId = i+1;
37 | new Thread(){
38 | @Override
39 | public void run() {
40 | try{
41 | DistributedLock dc = new DistributedLock(threadId);
42 | dc.createConnection(CONNECTION_STRING, SESSION_TIMEOUT);
43 | //GROUP_PATH不存在的话,由一个线程创建即可;
44 | synchronized (threadSemaphore){
45 | dc.createPath(GROUP_PATH, "该节点由线程" + threadId + "创建", true);
46 | }
47 | dc.getLock();
48 | } catch (Exception e){
49 | System.out.println(("【第"+threadId+"个线程】 抛出的异常:"));
50 | e.printStackTrace();
51 | }
52 | }
53 | }.start();
54 | }
55 | try {
56 | threadSemaphore.await();
57 | System.out.println("所有线程运行结束!");
58 | } catch (InterruptedException e) {
59 | e.printStackTrace();
60 | }
61 | }
62 |
63 | /**
64 | * 获取锁
65 | * @return
66 | */
67 | private void getLock() throws KeeperException, InterruptedException {
68 | selfPath = zk.create(SUB_PATH,null, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
69 | System.out.println(PREFIX_OF_THREAD+"创建锁路径:"+selfPath);
70 | if(checkMinPath()){
71 | getLockSuccess();
72 | }
73 | }
74 |
75 | /**
76 | * 创建锁节点
77 | * @param path 锁节点path
78 | * @param data 初始数据内容
79 | * @return
80 | */
81 | public boolean createPath( String path, String data, boolean needWatch) throws KeeperException, InterruptedException {
82 | if(zk.exists(path, needWatch)==null){
83 | System.out.println(PREFIX_OF_THREAD + "节点创建成功, Path: "
84 | + this.zk.create( path,
85 | data.getBytes(),
86 | ZooDefs.Ids.OPEN_ACL_UNSAFE,
87 | CreateMode.PERSISTENT)
88 | + ", content: " + data );
89 | }
90 | return true;
91 | }
92 |
93 | /**
94 | * 创建ZK连接
95 | * @param connectString ZK服务器地址列表
96 | * @param sessionTimeout Session超时时间
97 | */
98 | public void createConnection( String connectString, int sessionTimeout ) throws IOException, InterruptedException {
99 | zk = new ZooKeeper( connectString, sessionTimeout, this);
100 | connectedSemaphore.await();
101 | }
102 |
103 | /**
104 | * 获取锁成功
105 | */
106 | public void getLockSuccess() throws KeeperException, InterruptedException {
107 | if(zk.exists(this.selfPath,false) == null){
108 | System.out.println(PREFIX_OF_THREAD+"本节点已不在了...");
109 | return;
110 | }
111 | System.out.println(PREFIX_OF_THREAD + "获取锁成功,开始干活!");
112 | Thread.sleep(2000);
113 | releaseConnection();
114 | threadSemaphore.countDown();
115 | }
116 | /**
117 | * 关闭ZK连接
118 | */
119 | public void releaseConnection() {
120 | if ( this.zk !=null ) {
121 | try {
122 | this.zk.close();
123 | } catch ( InterruptedException e ) {}
124 | }
125 | System.out.println(PREFIX_OF_THREAD + "工作完毕,释放锁");
126 | }
127 |
128 | /**
129 | * 检查自己是不是最小的节点
130 | * @return
131 | */
132 | public boolean checkMinPath() throws KeeperException, InterruptedException {
133 | List subNodes = zk.getChildren(GROUP_PATH, false);
134 | Collections.sort(subNodes);
135 | //判断此节点
136 | int index = subNodes.indexOf( selfPath.substring(GROUP_PATH.length()+1));
137 | switch (index){
138 | case -1:{
139 | System.out.println(PREFIX_OF_THREAD+"本节点已不在了..."+selfPath);
140 | return false;
141 | }
142 | case 0:{
143 | System.out.println(PREFIX_OF_THREAD+"子节点中,我最小,可以获得锁了!哈哈"+selfPath);
144 | return true;
145 | }
146 | default:{
147 | this.waitPath = GROUP_PATH +"/"+ subNodes.get(index - 1);
148 | System.out.println(PREFIX_OF_THREAD+"排在我前面的节点是 "+waitPath);
149 | try{
150 | zk.getData(waitPath, true, new Stat());
151 | return false;
152 | }catch(KeeperException e){
153 | if(zk.exists(waitPath,false) == null){
154 | System.out.println(PREFIX_OF_THREAD+"排在我前面的"+waitPath+"已消失 ");
155 | return checkMinPath();
156 | }else{
157 | throw e;
158 | }
159 | }
160 | }
161 | }
162 | }
163 | @Override
164 | public void process(WatchedEvent event) {
165 | if(event == null){
166 | return;
167 | }
168 | Event.KeeperState keeperState = event.getState();
169 | Event.EventType eventType = event.getType();
170 | //已经是连接到zookeeper的状态
171 | if ( Event.KeeperState.SyncConnected == keeperState) {
172 | if ( Event.EventType.None == eventType ) {
173 | System.out.println(PREFIX_OF_THREAD + "成功连接上ZK服务器" );
174 | connectedSemaphore.countDown();
175 | }else if (event.getType() == Event.EventType.NodeDeleted && event.getPath().equals(waitPath)) {
176 | //监听节点被删除状态
177 | System.out.println(PREFIX_OF_THREAD + "watch说我前面那个节点挂了,我可以获取锁啦!!");
178 | try {
179 | //判断当前节点是否为最小节点
180 | if(checkMinPath()){
181 | getLockSuccess();
182 | }
183 | } catch (KeeperException e) {
184 | e.printStackTrace();
185 | } catch (InterruptedException e) {
186 | e.printStackTrace();
187 | }
188 | }
189 | }else if ( Event.KeeperState.Disconnected == keeperState ) {
190 | //监听断开
191 | System.out.println(PREFIX_OF_THREAD + "与ZK服务器断开连接" );
192 | } else if ( Event.KeeperState.AuthFailed == keeperState ) {
193 | //监听权限失败
194 | System.out.println(PREFIX_OF_THREAD + "权限检查失败" );
195 | } else if ( Event.KeeperState.Expired == keeperState ) {
196 | //监听会话失效
197 | System.out.println(PREFIX_OF_THREAD + "会话失效" );
198 | }
199 | }
200 | }
201 |
--------------------------------------------------------------------------------
/src/main/java/zookeeper/DistributedQueue/DistributedQueue.java:
--------------------------------------------------------------------------------
1 | package zookeeper.DistributedQueue;
2 |
3 | import org.apache.zookeeper.CreateMode;
4 | import org.apache.zookeeper.KeeperException;
5 | import org.apache.zookeeper.WatchedEvent;
6 | import org.apache.zookeeper.Watcher;
7 | import org.apache.zookeeper.ZooKeeper;
8 | import org.apache.zookeeper.ZooDefs.Ids;
9 |
10 | import java.io.IOException;
11 |
12 | /**
13 | * 链接:http://blog.fens.me/zookeeper-queue/
14 | *
15 | * 基于ZooKeeper现实的一种同步的分步式队列,当一个队列的成员都聚齐时,这个队列才可用,否则一直等待所有成员到达。
16 | *
17 | * 设计思路
18 | 创建一个父目录 /queue,每个成员都监控(Watch)标志位目录/queue/start 是否存在,然后每个成员都加入这个队列,
19 | 加入队列的方式就是创建 /queue/x(i)的临时目录节点,然后每个成员获取 /queue 目录的所有目录节点,也就是 x(i)。
20 | 判断 i 的值是否已经是成员的个数,如果小于成员个数等待 /queue/start 的出现,如果已经相等就创建 /queue/start。
21 |
22 | */
23 | public class DistributedQueue {
24 | public static void main(String[] args) throws Exception {
25 | //模拟app1通过zk1提交x1,app2通过zk2提交x2,app3通过zk3提交x3
26 | doAction(1);
27 | doAction(2);
28 | doAction(3);
29 | }
30 |
31 | //以此在集群的3台机器上加入某成员
32 | public static void doAction(int client) throws Exception {
33 | String host1 = "xxx:2181";
34 | String host2 = "xxx:2182";
35 | String host3 = "xxx:2183";
36 | ZooKeeper zk = null;
37 | switch (client) {
38 | case 1:
39 | zk = connection(host1);
40 | initQueue(zk);
41 | joinQueue(zk, 1);
42 | break;
43 | case 2:
44 | zk = connection(host2);
45 | initQueue(zk);
46 | joinQueue(zk, 2);
47 | break;
48 | case 3:
49 | zk = connection(host3);
50 | initQueue(zk);
51 | joinQueue(zk, 3);
52 | break;
53 | }
54 | }
55 |
56 | // 创建一个与服务器的连接
57 | public static ZooKeeper connection(String host) throws IOException {
58 | ZooKeeper zk = new ZooKeeper(host, 60000, new Watcher() {
59 | // 监控所有被触发的事件
60 | public void process(WatchedEvent event) {
61 | if (event.getType() == Event.EventType.NodeCreated && event.getPath().equals("/queue/start")) {
62 | System.out.println("Queue has Completed.Finish testing!!!");
63 | }
64 | }
65 | });
66 | return zk;
67 | }
68 |
69 | //初始化队列
70 | public static void initQueue(ZooKeeper zk) throws KeeperException, InterruptedException {
71 |
72 | System.out.println("WATCH => /queue/start");
73 |
74 | //当这个znode节点被改变时,将会触发当前Watcher
75 | zk.exists("/queue/start", true);
76 |
77 | //如果/queue目录为空,创建此节点
78 | if (zk.exists("/queue", false) == null) {
79 | System.out.println("create /queue task-queue");
80 | zk.create("/queue", "task-queue".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
81 | } else {
82 | System.out.println("/queue is exist!");
83 | }
84 | }
85 |
86 | //成员加入队列
87 | public static void joinQueue(ZooKeeper zk, int x) throws KeeperException, InterruptedException {
88 | System.out.println("create /queue/x" + x + " x" + x);
89 | zk.create("/queue/x" + x, ("x" + x).getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL);
90 | isCompleted(zk);
91 | }
92 |
93 | //判断队列是否已满
94 | public static void isCompleted(ZooKeeper zk) throws KeeperException, InterruptedException {
95 | //规定队列大小
96 | int size = 3;
97 | //查询成员数
98 | int length = zk.getChildren("/queue", true).size();
99 | System.out.println("Queue Complete:" + length + "/" + size);
100 | if (length >= size) {
101 | System.out.println("create /queue/start start");
102 | zk.create("/queue/start", "start".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
103 | }
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/zookeeper/HelloWorld.java:
--------------------------------------------------------------------------------
1 | package zookeeper;
2 |
3 | /**
4 | * Created by yaosheng on 2017/1/16.
5 | */
6 | import java.io.IOException;
7 | import org.apache.zookeeper.*;
8 | import org.apache.zookeeper.data.Stat;
9 |
10 | public class HelloWorld {
11 |
12 | public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
13 | //此语句执行完后执行process方法
14 | ZooKeeper zk = new ZooKeeper("xxx:2181", 300000, new DemoWatcher());//连接zk server
15 |
16 | String node = "/app1";
17 | Stat stat = zk.exists(node, false);//检测/app1是否存在
18 | if (stat == null) {
19 | //创建节点
20 | String createResult = zk.create(node, "test".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
21 | System.out.println(createResult);
22 | }
23 | //获取节点的值
24 | byte[] b = zk.getData(node, false, stat);
25 | System.out.println(new String(b));
26 | zk.close();
27 |
28 | }
29 |
30 | static class DemoWatcher implements Watcher {
31 | @Override
32 | public void process(WatchedEvent event) {
33 | System.out.println("----------->");
34 | System.out.println("path:" + event.getPath());
35 | System.out.println("type:" + event.getType());
36 | System.out.println("stat:" + event.getState());
37 | System.out.println("<-----------");
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/main/resources/helloDubbo/consumer.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
--------------------------------------------------------------------------------
/src/main/resources/helloDubbo/provider.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------