首先这里用的springboot版本为2.2.2 ,zookeeper用的版本是 3.4.14 ,开发工具用的是java 开发神奇idea
这里的pom的代码如下
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.ext</groupId>
<artifactId>demozk</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demozk</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.14</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.mateu/lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
要说明的是 curator 用的是4.0 的版本所以要去掉自身的zookeeper 因为它自己的版本是3.5的,同时要加上我们自己用的3.4的版本,否则会报错的。
监听代码如下
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.api.CuratorEvent;
import org.apache.curator.framework.api.CuratorListener;
import org.apache.curator.framework.api.CuratorEventType;
import org.apache.zookeeper.WatchedEvent;
public class MyCuratorListener implements CuratorListener {
@Override
public void eventReceived(CuratorFramework client, CuratorEvent event) throws Exception {
CuratorEventType type = event.getType();
if(type == CuratorEventType.WATCHED){
WatchedEvent watchedEvent = event.getWatchedEvent();
String path = watchedEvent.getPath();
System.out.println(watchedEvent.getType()+" -- "+ path);
// 重新设置改节点监听
if(null != path)
client.checkExists().watched().forPath(path);
}
}
}
zookeeper的配置代码如下:
import com.ext.demozk.common.MyCuratorListener;
import org.springframework.context.annotation.Configuration;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ZookeeperConfig {
/**
* Curator Apache
* 供的个访问Zookeeper的工具包,封装了这些低级别操作同时也提供一些高级服务,比如分布式锁、领导选取
* @return
*/
@Bean
public CuratorFramework curatorFramework(){
// ExponentialBackoffRetry是种重连策略,每次重连的间隔会越来越长,1000毫秒是初始化的间隔时间,3代表尝试重连次数。
ExponentialBackoffRetry retry = new ExponentialBackoffRetry(1000, 3);
// 创建client
CuratorFramework curatorFramework = CuratorFrameworkFactory.newClient("localhost:2181", retry);
// 添加watched 监听器
curatorFramework.getCuratorListenable().addListener(new MyCuratorListener());
curatorFramework.start();
return curatorFramework;
}
}
zookeeper锁的代码如下
import lombok.extern.slf4j.Slf4j;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessLock;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class CuratorLockService {
@Autowired
private CuratorFramework client;
/**
* 分布式锁的初始路径
*/
private String lockPath = "/lock/test";
public void lockTest(String value) throws Exception {
lockPath = lockPath + "/" + value;
log.info("尝试执行业务" + value);
// 创建分布式锁
InterProcessMutex lock = new InterProcessMutex(client, lockPath);
try {
// 获取锁资源
if (lock.acquire(10, TimeUnit.HOURS)) {
log.info("业务逻辑模拟,耗时25s");
Thread.sleep(25000);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
lock.release();
log.info("释放锁资源");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
controller层调用 service层的代码如下:
import com.ext.demozk.entity.InvokeResult;
import com.ext.demozk.service.CuratorLockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class testController {
@Autowired
CuratorLockService lockService;
@GetMapping("lock/test")
public String lock(String value) throws Exception{
lockService.lockTest(value);
return "success";
}
}
在使用的过程中出现了一些问题如下:
org.apache.zookeeper.KeeperException$UnimplementedException: KeeperErrorCode = Unimplemented for /lock/test/11/_c_6fe4fe88-fcfe-490c-bafe-bafe7e0cb4bd-lock-
at org.apache.zookeeper.KeeperException.create(KeeperException.java:103) ~[zookeeper-3.5.1-alpha.jar:3.5.1-alpha-1693007]
at org.apache.zookeeper.KeeperException.create(KeeperException.java:51) ~[zookeeper-3.5.1-alpha.jar:3.5.1-alpha-1693007]
at org.apache.zookeeper.ZooKeeper.create(ZooKeeper.java:1297) ~[zookeeper-3.5.1-alpha.jar:3.5.1-alpha-1693007]
at org.apache.curator.framework.imps.CreateBuilderImpl$17.call(CreateBuilderImpl.java:1075) ~[curator-framework-3.3.0.jar:3.3.0]
at org.apache.curator.framework.imps.CreateBuilderImpl$17.call(CreateBuilderImpl.java:1058) ~[curator-framework-3.3.0.jar:3.3.0]
at org.apache.curator.connection.StandardConnectionHandlingPolicy.callWithRetry(StandardConnectionHandlingPolicy.java:67) ~[curator-client-3.3.0.jar:na]
at org.apache.curator.RetryLoop.callWithRetry(RetryLoop.java:100) ~[curator-client-3.3.0.jar:na]
at org.apache.curator.framework.imps.CreateBuilderImpl.pathInForeground(CreateBuilderImpl.java:1055) ~[curator-framework-3.3.0.jar:3.3.0]
at org.apache.curator.framework.imps.CreateBuilderImpl.protectedPathInForeground(CreateBuilderImpl.java:524) ~[curator-framework-3.3.0.jar:3.3.0]
at org.apache.curator.framework.imps.CreateBuilderImpl.forPath(CreateBuilderImpl.java:514) ~[curator-framework-3.3.0.jar:3.3.0]
at org.apache.curator.framework.imps.CreateBuilderImpl.forPath(CreateBuilderImpl.java:492) ~[curator-framework-3.3.0.jar:3.3.0]
at org.apache.curator.framework.imps.CreateBuilderImpl.forPath(CreateBuilderImpl.java:44) ~[curator-framework-3.3.0.jar:3.3.0]
at org.apache.curator.framework.recipes.locks.StandardLockInternalsDriver.createsTheLock(StandardLockInternalsDriver.java:54) ~[curator-recipes-3.3.0.jar:na]
at org.apache.curator.framework.recipes.locks.LockInternals.attemptLock(LockInternals.java:218) ~[curator-recipes-3.3.0.jar:na]
at org.apache.curator.framework.recipes.locks.InterProcessMutex.internalLock(InterProcessMutex.java:232) ~[curator-recipes-3.3.0.jar:na]
at org.apache.curator.framework.recipes.locks.InterProcessMutex.acquire(InterProcessMutex.java:108) ~[curator-recipes-3.3.0.jar:na]
at com.ext.demozk.service.CuratorLockService.lockTest(CuratorLockService.java:36) ~[classes/:na]
at com.ext.demozk.controller.testController.lock(testController.java:17) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_221]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_221]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_221]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_221]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) ~[spring-web-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) ~[tomcat-embed-core-9.0.29.jar:9.0.29]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.2.RELEASE.jar:5.2.2.RELEASE]
最终发现的问题是zookeeper 的版本不一致导致错误,pom文件改为下面的 吧curator-recipes 3.0版本改为下面的4.0版本
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.0.0</version>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.14</version>
</dependency>
然后就解决问题了,欢迎大家批评指正。