以上就是给各位分享使用Zookeeper实现负载均衡原理,其中也会对zookeeper做负载均衡进行解释,同时本文还将给你拓展ActiveMQ建立brokercluster实现负载均衡、Dubbo与Z
以上就是给各位分享使用Zookeeper实现负载均衡原理,其中也会对zookeeper做负载均衡进行解释,同时本文还将给你拓展ActiveMQ建立broker cluster实现负载均衡、Dubbo 与 Zookeeper、SpringMVC 整合和使用(负载均衡、容错)、dubbo负载均衡与服务降级以及Zookeeper认证、java使用zookeeper实现的分布式锁示例等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:- 使用Zookeeper实现负载均衡原理(zookeeper做负载均衡)
- ActiveMQ建立broker cluster实现负载均衡
- Dubbo 与 Zookeeper、SpringMVC 整合和使用(负载均衡、容错)
- dubbo负载均衡与服务降级以及Zookeeper认证
- java使用zookeeper实现的分布式锁示例
使用Zookeeper实现负载均衡原理(zookeeper做负载均衡)
思路
使用Zookeeper实现负载均衡原理,服务器端将启动的服务注册到,zk注册中心上,采用临时节点。客户端从zk节点上获取最新服务节点信息,本地使用负载均衡算法,随机分配服务器。
创建项目工程
Maven依赖
<dependencies>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.8</version>
</dependency>
</dependencies>
创建Server服务端
ZkServerScoekt服务
//##ServerScoekt服务端
public class ZkServerScoekt implements Runnable {
private int port = 18080;
public static void main(String[] args) throws IOException {
int port = 18080;
ZkServerScoekt server = new ZkServerScoekt(port);
Thread thread = new Thread(server);
thread.start();
}
public ZkServerScoekt(int port) {
this.port = port;
}
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
System.out.println("Server start port:" + port);
Socket socket = null;
while (true) {
socket = serverSocket.accept();
new Thread(new ServerHandler(socket)).start();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (Exception e2) {
}
}
}
}
ZkServerClient
public class ZkServerClient {
public static List<String> listServer = new ArrayList<String>();
public static void main(String[] args) {
initServer();
ZkServerClient client= new ZkServerClient();
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String name;
try {
name = console.readLine();
if ("exit".equals(name)) {
System.exit(0);
}
client.send(name);
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 注册所有server
public static void initServer() {
listServer.clear();
listServer.add("127.0.0.1:18080");
}
// 获取当前server信息
public static String getServer() {
return listServer.get(0);
}
public void send(String name) {
String server = ZkServerClient.getServer();
String[] cfg = server.split(":");
Socket socket = null;
BufferedReader in = null;
PrintWriter out = null;
try {
socket = new Socket(cfg[0], Integer.parseInt(cfg[1]));
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
out.println(name);
while (true) {
String resp = in.readLine();
if (resp == null)
break;
else if (resp.length() > 0) {
System.out.println("Receive : " + resp);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
ServerHandler
public class ServerHandler implements Runnable {
private Socket socket;
public ServerHandler(Socket socket) {
this.socket = socket;
}
public void run() {
BufferedReader in = null;
PrintWriter out = null;
try {
in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
out = new PrintWriter(this.socket.getOutputStream(), true);
String body = null;
while (true) {
body = in.readLine();
if (body == null)
break;
System.out.println("Receive : " + body);
out.println("Hello, " + body);
}
} catch (Exception e) {
if (in != null) {
try {
in.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
if (out != null) {
out.close();
}
if (this.socket != null) {
try {
this.socket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
this.socket = null;
}
}
}
}
改造ZkServerScoekt
public class ZkServerScoekt implements Runnable {
private static int port = 18081;
public static void main(String[] args) throws IOException {
ZkServerScoekt server = new ZkServerScoekt(port);
Thread thread = new Thread(server);
thread.start();
}
public ZkServerScoekt(int port) {
this.port = port;
}
public void regServer() {
// 向ZooKeeper注册当前服务器
ZkClient client = new ZkClient("127.0.0.1:2181", 60000, 1000);
String path = "/test/server" + port;
if (client.exists(path))
client.delete(path);
client.createEphemeral(path, "127.0.0.1:" + port);
}
public void run() {
ServerSocket serverSocket = null;
try {
serverSocket = new ServerSocket(port);
regServer();
System.out.println("Server start port:" + port);
Socket socket = null;
while (true) {
socket = serverSocket.accept();
new Thread(new ServerHandler(socket)).start();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (Exception e2) {
}
}
}
}
改造ZkServerClientScoekt
public class ZkServerClient {
public static List<String> listServer = new ArrayList<String>();
public static void main(String[] args) {
initServer();
ZkServerClient client = new ZkServerClient();
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String name;
try {
name = console.readLine();
if ("exit".equals(name)) {
System.exit(0);
}
client.send(name);
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 注册所有server
public static void initServer() {
String path = "/test";
final ZkClient zkClient = new ZkClient("127.0.0.1:2181", 6000, 1000);
List<String> children = zkClient.getChildren(path);
for (String ipServer : children) {
listServer.add((String) zkClient.readData(path + "/" + ipServer));
}
System.out.println("####从注册中心获取服务信息####listServer:" + listServer.toString());
// 监听事件
zkClient.subscribeChildChanges(path, new IZkChildListener() {
public void handleChildChange(String parentPath, List<String> currentChilds) throws Exception {
listServer.clear();
for (String ctPath : currentChilds) {
listServer.add(zkClient.readData(parentPath) + "/" + ctPath);
}
System.out.println("####节点事件监听发生变化### listServer:" + listServer.toString());
}
});
// listServer.clear();
// listServer.add("127.0.0.1:8080");
}
private static int reqestCount = 1;
// 获取当前server信息
public static String getServer() {
int serverCount = listServer.size();
String serverHost = listServer.get(reqestCount / serverCount);
reqestCount++;
return serverHost;
}
public void send(String name) {
String server = ZkServerClient.getServer();
String[] cfg = server.split(":");
Socket socket = null;
BufferedReader in = null;
PrintWriter out = null;
try {
socket = new Socket(cfg[0], Integer.parseInt(cfg[1]));
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(socket.getOutputStream(), true);
out.println(name);
while (true) {
String resp = in.readLine();
if (resp == null)
break;
else if (resp.length() > 0) {
System.out.println("Receive : " + resp);
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (out != null) {
out.close();
}
if (in != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
使用Zookeeper实现选举策略
场景
有一个向外提供的服务,服务必须7*24小时提供服务,不能有单点故障。所以采用集群的方式,采用master、slave的结构。一台主机多台备机。主机向外提供服务,备机负责监听主机的状态,一旦主机宕机,备机要迅速接代主机继续向外提供服务。从备机选择一台作为主机,就是master选举。
原理分析
右边三台主机会尝试创建master节点,谁创建成功了,就是master,向外提供。其他两台就是slave。
所有slave必须关注master的删除事件(临时节点,如果服务器宕机了,Zookeeper会自动把master节点删除)。如果master宕机了,会进行新一轮的master选举。本次我们主要关注master选举,服务注册、发现先不讨论。
使用Zookeeper原理
» 领导者(leader),负责进行投票的发起和决议,更新系统状态
» 学习者(learner),包括跟随者(follower)和观察者(observer),follower用于接受客户端请求并想客户端返回结果,在选主过程中参与投票
» Observer可以接受客户端连接,将写请求转发给leader,但observer不参加投票过程,只同步leader的状态,observer的目的是为了扩展系统,提高读取速度
» 客户端(client),请求发起方
• Zookeeper的核心是原子广播,这个机制保证了各个Server之间的同步。实现这个机制的协议叫做Zab协
议。Zab协议有两种模式,它们分别是恢复模式(选主)和广播模式(同步)。当服务启动或者在领导者
崩溃后,Zab就进入了恢复模式,当领导者被选举出来,且大多数Server完成了和leader的状态同步以后
,恢复模式就结束了。状态同步保证了leader和Server具有相同的系统状态。
• 为了保证事务的顺序一致性,zookeeper采用了递增的事务id号(zxid)来标识事务。所有的提议(
proposal)都在被提出的时候加上了zxid。实现中zxid是一个64位的数字,它高32位是epoch用来标识
leader关系是否改变,每次一个leader被选出来,它都会有一个新的epoch,标识当前属于那个leader的
统治时期。低32位用于递增计数。
• 每个Server在工作过程中有三种状态:
LOOKING:当前Server不知道leader是谁,正在搜寻
LEADING:当前Server即为选举出来的leader
FOLLOWING:leader已经选举出来,当前Server与之同步
ActiveMQ建立broker cluster实现负载均衡
最近在测试activeMQ这个开源中间件,在建立broker-cluster实现负载均衡时出现一个问题,请教一下:
<networkConnectors>
<networkConnector uri="static:(tcp://host1:61616,tcp://host2:61616)" duplex="true"/>
</networkConnectors>
配置是按照给的例子 activemq-static-network-broker2.xml进行的,我用一个发送者,开两个消费者,一个消费host1,另一个消费host2.看到两者消费的消息不一样多,大体host1这支是另一支的2倍;后来我host1开一支消费,host2开2支消费,此时两个host消费相等。
activemq实现的负载均衡就是这样子吗,不是应该每支consumer消费相等吗?
Dubbo 与 Zookeeper、SpringMVC 整合和使用(负载均衡、容错)
互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,Dubbo 是一个分布式服务框架,在这种情况下诞生的。现在核心业务抽取出来,作为独立的服务,使前端应用能更快速和稳定的响应。
第一:介绍 Dubbo 背景
大规模服务化之前,应用可能只是通过 RMI 或 Hessian 等工具,简单的暴露和引用远程服务,通过配置服务的 URL 地址进行调用,通过 F5 等硬件进行负载均衡。
(1) 当服务越来越多时,服务 URL 配置管理变得非常困难,F5 硬件负载均衡器的单点压力也越来越大。
此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。
并通过在消费方获取服务提供方地址列表,实现软负载均衡和 Failover,降低对 F5 硬件负载均衡器的依赖,也能减少部分成本。
(2) 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。
这时,需要自动画出应用间的依赖关系图,以帮助架构师理清理关系。
(3) 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?
为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。
其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阀值,记录此时的访问量,再以此访问量乘以机器数反推总容量。
第二:Dubbo 的简介
Dubbo 是一个分布式服务框架,解决了上面的所面对的问题,Dubbo 的架构如图所示:
节点角色说明:
Provider: 暴露服务的服务提供方。
Consumer: 调用远程服务的服务消费方。
Registry: 服务注册与发现的注册中心。
Monitor: 统计服务的调用次调和调用时间的监控中心。
Container: 服务运行容器。
调用关系说明:
0. 服务容器负责启动,加载,运行服务提供者。
1. 服务提供者在启动时,向注册中心注册自己提供的服务。
2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
Dubbo 提供了很多协议,Dubbo 协议、RMI 协议、Hessian 协议,我们查看 Dubbo 源代码,有各种协议的实现,如图所示:
我们之前没用 Dubbo 之前时,大部分都使用 Hessian 来使用我们服务的暴露和调用,利用 HessianProxyFactory 调用远程接口。
上面是参考了 Dubbo 官方网介绍,接下来我们来介绍 SpringMVC、Dubbo、Zookeeper 整合使用。
第三:Dubbo 与 Zookeeper、SpringMVC 整合使用
第一步:在 Linux 上安装 Zookeeper
Zookeeper 作为 Dubbo 服务的注册中心,Dubbo 原先基于数据库的注册中心,没采用 Zookeeper,Zookeeper 一个分布式的服务框架,是树型的目录服务的数据存储,能做到集群管理数据 ,这里能很好的作为 Dubbo 服务的注册中心,Dubbo 能与 Zookeeper 做到集群部署,当提供者出现断电等异常停机时,Zookeeper 注册中心能自动删除提供者信息,当提供者重启时,能自动恢复注册数据,以及订阅请求。我们先在 linux 上安装 Zookeeper,我们安装最简单的单点,集群比较麻烦。
(1)下载 Zookeeper-3.4.6.tar.gz 地址 http://www.apache.org/dist/zookeeper/
(2) 我们放到 Linux 下的一个文件夹,然后解压:
#tar zxvf zookeeper-3.4.6.tar.gz
(3)然后在对应的 zookeeper-3.4.6/conf 下有一个文件 zoo_sample.cfg 的这个文件里面配置了监听客户端连接的端口等一些信息,Zookeeper 在启动时会找 zoo.cfg 这个文件作为默认配置文件,所以我们复制一个名称为 zoo.cfg 的文件,如图所示:
我们查看一下这个文件的里面的一些配置信息,如图所示:
获取【下载地址】 最主流的 Java 后台 SSM 框架 springmvc spring mybatis 项目源码
说明:
clientPort:监听客户端连接的端口。
tickTime:基本事件单元,以毫秒为单位。它用来控制心跳和超时,默认情况下最小的会话超时时间为两倍的 tickTime。
我们可以对配置文件的端口等或者进行高级配置和集群配置例如:maxClientCnxns:限制连接到 ZooKeeper 的客户端的数量等
(4) 启动 Zookeeper 的服务,如图所示:
到这边 Zookeeper 的安装和配置完成
第二步:配置 dubbo-admin 的管理页面,方便我们管理页面
(1) 下载 dubbo-admin-2.4.1.war 包,在 Linux 的 tomcat 部署,先把 dubbo-admin-2.4.1 放在 tomcat 的 webapps/ROOT 下,然后进行解压:
#jar -xvf dubbo-admin-2.4.1.war
(2) 然后到 webapps/ROOT/WEB-INF 下,有一个 dubbo.properties 文件,里面指向 Zookeeper ,使用的是 Zookeeper 的注册中心,如图所示:
(3) 然后启动 tomcat 服务,用户名和密码:root, 并访问服务,显示登陆页面,说明 dubbo-admin 部署成功,如图所示:
第三步:SpringMVC 与 Dubbo 的整合,这边使用的 Maven 的管理项目
第一:我们先开发服务注册的,就是提供服务,项目结构如图所示:
(1)test-maven-api 项目加入了一个服务接口,代码如下:
- public interface TestRegistryService {
- public String hello(String name);
- }
(2)test-maven-console 在 pom.xml 加入 Dubbo 和 Zookeeper 的 jar 包、引用 test-maven-api 的 jar 包,代码如下:
- <dependency>
- <groupId>cn.test</groupId>
- <artifactId>test-maven-api</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>dubbo</artifactId>
- <version>2.5.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.zookeeper</groupId>
- <artifactId>zookeeper</artifactId>
- <version>3.4.6</version>
- </dependency>
- <dependency>
- <groupId>com.github.sgroschupf</groupId>
- <artifactId>zkclient</artifactId>
- <version>0.1</version>
- </dependency>
(3) test-maven-console 实现具体的服务,代码如下:
- @Service("testRegistryService")
- ublic class TestRegistryServiceImpl implements TestRegistryService {
- public String hello(String name) {
- return "hello"+name;
- }
(4) 我们服务以及实现好了,这时要暴露服务,代码如下:
- <?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:jee="http://www.springframework.org/schema/jee"
- xmlns:tx="http://www.springframework.org/schema/tx"
- <span >xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"</span>
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
- http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
- <span >http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd</span>
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"
- default-lazy-init="false" >
- <!-- 提供方应用名称信息,这个相当于起一个名字,我们 dubbo 管理页面比较清晰是哪个应用暴露出来的 -->
- <dubbo:application name="dubbo_provider"></dubbo:application>
- <!-- 使用 zookeeper 注册中心暴露服务地址 -->
- <dubbo:registry address="zookeeper://127.0.0.1:2181" check="false" subscribe="false" register=""></dubbo:registry>
- <!-- 要暴露的服务接口 -->
- <dubbo:service interface="cn.test.dubbo.registry.service.TestRegistryService" ref="testRegistryService" />
- </beans>
说明:
dubbo:registry 标签一些属性的说明:
1)register 是否向此注册中心注册服务,如果设为 false,将只订阅,不注册。
2)check 注册中心不存在时,是否报错。
3)subscribe 是否向此注册中心订阅服务,如果设为 false,将只注册,不订阅。
4)timeout 注册中心请求超时时间 (毫秒)。
5)address 可以 Zookeeper 集群配置,地址可以多个以逗号隔开等。
dubbo:service 标签的一些属性说明:
1)interface 服务接口的路径
2)ref 引用对应的实现类的 Bean 的 ID
3)registry 向指定注册中心注册,在多个注册中心时使用,值为 <dubbo:registry> 的 id 属性,多个注册中心 ID 用逗号分隔,如果不想将该服务注册到任何 registry,可将值设为 N/A
4)register 默认 true ,该协议的服务是否注册到注册中心。
(5) 启动项目,然后我们在 Dubbo 管理页面上显示,已经暴露的服务,但显示还没有消费者,因为我们还没实现消费者服务,如图所示:
第二:我们在开发服务消费者,就是调用服务,我们在新建一个新的消费者项目结构如图所示:
(1)test-maven-server-console 的 pom.xml 引入 Dubbo 和 Zookeeper 的 jar 包、test-maven-api 的 jar 包,因为引入 test-maven-api 的 jar 包,我们在项目中调用像在本地调用一样。代码如下:
[java] view plain copy
- <dependency>
- <groupId>cn.test</groupId>
- <artifactId>test-maven-api</artifactId>
- <version>0.0.1-SNAPSHOT</version>
- </dependency>
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>dubbo</artifactId>
- <version>2.5.3</version>
- </dependency>
- <dependency>
- <groupId>org.apache.zookeeper</groupId>
- <artifactId>zookeeper</artifactId>
- <version>3.4.6</version>
- </dependency>
- <dependency>
- <groupId>com.github.sgroschupf</groupId>
- <artifactId>zkclient</artifactId>
- <version>0.1</version>
- </dependency>
(2)test-maven-server-console 项目的具体实现,代码如下:
[java] view plain copy
- @Controller
- public class IndexController {
- @Autowired
- private TestRegistryService testRegistryService;
- @RequestMapping("/hello")
- public String index(Model model){
- String name=testRegistryService.hello("zz");
- System.out.println("xx=="+name);
- return "";
- }
- }
(3) 我们要引用的地址,代码如下:
[java] view plain copy
- <?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:jee="http://www.springframework.org/schema/jee"
- xmlns:tx="http://www.springframework.org/schema/tx"
- <span ><span >xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"</span></span>
- xmlns:context="http://www.springframework.org/schema/context"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
- http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
- <span >http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd</span>
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd"
- default-lazy-init="false" >
- <dubbo:application name="dubbo_consumer"></dubbo:application>
- <!-- 使用 zookeeper 注册中心暴露服务地址 -->
- <dubbo:registry address="zookeeper://192.168.74.129:2181" check="false"></dubbo:registry>
- <!-- 要引用的服务 -->
- <dubbo:reference interface="cn.test.dubbo.registry.service.TestRegistryService" id="testRegistryService"></dubbo:reference>
- </beans>
说明:
dubbo:reference 的一些属性的说明:
1)interface 调用的服务接口
2)check 启动时检查提供者是否存在,true 报错,false 忽略
3)registry 从指定注册中心注册获取服务列表,在多个注册中心时使用,值为 <dubbo:registry> 的 id 属性,多个注册中心 ID 用逗号分隔
4)loadbalance 负载均衡策略,可选值:random,roundrobin,leastactive,分别表示:随机,轮循,最少活跃调用
(4) 项目启动,Dubbo 管理页面,能看到消费者,如图所示:
(5) 然后访问消费者项目,Controller 层能像调用本地一样调用服务的具体实现,如图所示:
Dubbo 提供了多种容错方案,包括负载均衡这些,如图所示:
dubbo负载均衡与服务降级以及Zookeeper认证
1.Dubbo集群与负载均衡
2.服务降级:指的是当服务器资源紧张的时候,暂停掉一些不重要的微服务,从而将所有的服务器的资源统一交由另外一个核心的微服务处理
• 【dubbo-api】如果要想实现服务降级的处理,在Dubbo之中需要为业务接口设计一个降级时的处理业务类即可
package com.yootk.dubbo.service;
import com.yootk.dubbo.service.IMessageService;
import com.yootk.dubbo.vo.Message;
public class IMessageServiceMock implements IMessageService {
@Override
public Message echo(Message msg) {
Message echoMessage = new Message() ;
echoMessage.setSender("【ECHO】Nothing...");
echoMessage.setTitle("【ECHO】Nothing...");
echoMessage.setContent("【ECHO】Nothing...");
return echoMessage;
}
}
• 【dubbo-echo-consumer】所有的服务降级的处理操作全部都是在客户端上处理完成的,修改客户端的接口注入配置
@Reference(mock="true",check=false)
private IMessageService messageInstance;
那么现在就有一个问题了,如果所有的业务接口都使用这样的一种Mock实现类型,这个时候一定会造成代码的维护困难,所以还有一种简单的做法,让数据直接返回null,一旦服务不可用,返回一个null对象,而这种配置只需要在消费端的注解上定义即可。
@Reference(mock="return null",check=false)
private IMessageService messageInstance;
3.ZooKeeper认证:在以后实际的开发之中,一定要为ZooKeeper设置ACL认证,才可以更好的进行注册内容的保护,同时防止其他用户盗取你的网络资源。
• 【zookeeper-cluster-*】为根目录设置Zookeeper的认证信息,同时建议删除已经存在的所有dubbo路径信息
• 删除当前已经存在的所有dubbo的路径:deleteall /dubbo
• 追加一个新的数字认证信息:addauth digest zkuser:hellolee
• 为zkuser的账户设置权限:setAcl / auth:zkuser:hellolee:crwda
• 【zookeeper-echo-*】修改服务提供者与服务消费者的dubbo.properties配置文件,追加账户信息:
dubbo.registry.username=zkuser
dubbo.registry.password=hellolee
• 【zookeeper-echo-*】修改服务提供者与服务消费者的spring配置文件
• 【zookeeper-echo-provider】spring-dubbo-provider.xml:
<!-- 在进行Dubbo服务注册的时候一定要将服务注册到ZooKeeper之中 -->
<dubbo:registry protocol="zookeeper" address="${dubbo.registry.address}"
timeout="${dubbo.provider.timeout}" file="${dubbo.registry.file}"
username="${dubbo.registry.username}"
password="${dubbo.registry.password}" client="curator"/>
• 【zookeeper-echo-provider】spring-dubo-consumer.xml:
<!-- 在进行Dubbo服务注册的时候一定要将服务注册到ZooKeeper之中 -->
<dubbo:registry protocol="zookeeper" address="${dubbo.registry.address}"
timeout="${dubbo.provider.timeout}"
username="${dubbo.registry.username}"
password="${dubbo.registry.password}" client="curator"/>
4.Dubbo直连与Token认证
• 修改服务提供端的配置文件,引入token的配置项:
<dubbo:provider timeout="${dubbo.provider.timeout}"
dispatcher="message" threadpool="fixed" threads="8" token="true"/>
• 修改消费端的@Reference注解,将其设置为默认形式的引用配置:在日后所有的项目开发之中,dubbo服务端一定要开启token认证,这才是标准的项目开发。
@Reference(mock="return null",check=false)
private IMessageService messageInstance;
java使用zookeeper实现的分布式锁示例
这篇文章主要介绍了java使用zookeeper实现的分布式锁示例,需要的朋友可以参考下
使用zookeeper实现的分布式锁
分布式锁,实现了Lock接口
复制代码 代码如下:
package com.concurrent;import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
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;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
/**
distributedLock lock = null;
try {
lock = new distributedLock("127.0.0.1:2182","test");
lock.lock();
//do something...
} catch (Exception e) {
e.printstacktrace();
}
finally {
if(lock != null)
lock.unlock();
}
* @author xueliang
*
*/
public class distributedLock implements Lock, Watcher{
private ZooKeeper zk;
private String root = "/locks";//根
private String lockName;//竞争资源的标志
private String waitNode;//等待前一个锁
private String myZnode;//当前锁
private CountDownLatch latch;//计数器
private int sessionTimeout = 30000;
private List exception = new ArrayList();
/**
* 创建分布式锁,使用前请确认config配置的zookeeper服务可用
* @param config 127.0.0.1:2181
* @param lockName 竞争资源标志,lockName中不能包含单词lock
*/
public distributedLock(String config, String lockName){
this.lockName = lockName;
// 创建一个与服务器的连接
try {
zk = new ZooKeeper(config, sessionTimeout, this);
Stat stat = zk.exists(root, false);
if(stat == null){
// 创建根节点
zk.create(root, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.PERSISTENT);
}
} catch (IOException e) {
exception.add(e);
} catch (KeeperException e) {
exception.add(e);
} catch (InterruptedException e) {
exception.add(e);
}
}
/**
* zookeeper节点的监视器
*/
public void process(WatchedEvent event) {
if(this.latch != null) {
this.latch.countDown();
}
}
public void lock() {
if(exception.size() > 0){
throw new LockException(exception.get(0));
}
try {
if(this.tryLock()){
System.out.println("Thread " + Thread.currentThread().getId() + " " +myZnode + " get lock true");
return;
}
else{
waitForLock(waitNode, sessionTimeout);//等待锁
}
} catch (KeeperException e) {
throw new LockException(e);
} catch (InterruptedException e) {
throw new LockException(e);
}
}
public boolean tryLock() {
try {
String splitStr = "_lock_";
if(lockName.contains(splitStr))
throw new LockException("lockName can not contains \u000B");
//创建临时子节点
myZnode = zk.create(root + "/" + lockName + splitStr, new byte[0], ZooDefs.Ids.OPEN_ACL_UNSAFE,CreateMode.EPHEMERAL_SEQUENTIAL);
System.out.println(myZnode + " is created ");
//取出所有子节点
List subNodes = zk.getChildren(root, false);
//取出所有lockName的锁
List lockObjNodes = new ArrayList();
for (String node : subNodes) {
String _node = node.split(splitStr)[0];
if(_node.equals(lockName)){
lockObjNodes.add(node);
}
}
Collections.sort(lockObjNodes);
System.out.println(myZnode + "==" + lockObjNodes.get(0));
if(myZnode.equals(root+"/"+lockObjNodes.get(0))){
//如果是最小的节点,则表示取得锁
return true;
}
//如果不是最小的节点,找到比自己小1的节点
String subMyZnode = myZnode.substring(myZnode.lastIndexOf("/") + 1);
waitNode = lockObjNodes.get(Collections.binarySearch(lockObjNodes, subMyZnode) - 1);
} catch (KeeperException e) {
throw new LockException(e);
} catch (InterruptedException e) {
throw new LockException(e);
}
return false;
}
public boolean tryLock(long time, TimeUnit unit) {
try {
if(this.tryLock()){
return true;
}
return waitForLock(waitNode,time);
} catch (Exception e) {
e.printstacktrace();
}
return false;
}
private boolean waitForLock(String lower, long waitTime) throws InterruptedException, KeeperException {
Stat stat = zk.exists(root + "/" + lower,true);
//判断比自己小一个数的节点是否存在,如果不存在则无需等待锁,同时注册监听
if(stat != null){
System.out.println("Thread " + Thread.currentThread().getId() + " waiting for " + root + "/" + lower);
this.latch = new CountDownLatch(1);
this.latch.await(waitTime, TimeUnit.MILLISECONDS);
this.latch = null;
}
return true;
}
public void unlock() {
try {
System.out.println("unlock " + myZnode);
zk.delete(myZnode,-1);
myZnode = null;
zk.close();
} catch (InterruptedException e) {
e.printstacktrace();
} catch (KeeperException e) {
e.printstacktrace();
}
}
public void lockInterruptibly() throws InterruptedException {
this.lock();
}
public Condition newCondition() {
return null;
}
public class LockException extends RuntimeException {
private static final long serialVersionUID = 1L;
public LockException(String e){
super(e);
}
public LockException(Exception e){
super(e);
}
}
}
上一篇:java 中 zookeeper简单使用下一篇:详解 Java静态代理 热门搜索:
redis分布式锁实现原理
java实例
使用实例
分布式锁
使用示例
相关文章
java使用zookeeper实现的分布式锁示例
2021-10-10阅读(9392)评论(0)推荐()这篇文章主要介绍了java使用zookeeper实现的分布式锁示例,需要的朋友可以参考下
分析ZooKeeper分布式锁的实现
2021-10-19阅读(9576)评论(0)推荐()在分布式的情况下,sychornized 和 Lock 已经不能满足我们的要求了,那么就需要使用第三方的锁了,这里我们就使用 ZooKeeper 来实现一个分布...
ZooKeeper 实现分布式锁的方法示例
2021-11-18阅读(4303)评论(0)推荐()这篇文章主要介绍了ZooKeeper 实现分布式锁的方法示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
zookeeper实现分布式锁
2021-09-20阅读(5325)评论(0)推荐()这篇文章主要为大家详细介绍了基于zookeeper实现分布式锁,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
浅谈Java(SpringBoot)基于zookeeper的分布式锁实现
2021-10-10阅读(6450)评论(0)推荐()这篇文章主要介绍了Java(SpringBoot)基于zookeeper的分布式锁实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价...
C# 实现Zookeeper分布式锁的参考示例
2021-10-06阅读(3932)评论(0)推荐()Zookeeper分布式锁的原理是巧妙的是使用了znode临时节点的特点和监听(watcher)机制,监听机制很简单,就是我们可以给znode添加一个监听器,当...
如何操作Redis和zookeeper实现分布式锁
2021-11-19阅读(2654)评论(0)推荐()这篇文章主要介绍了如何操作Redis和zookeeper实现分布式锁的相关资料,需要的朋友可以参考下
取消
有人回复时邮件通知我
提交评论
我们今天的关于使用Zookeeper实现负载均衡原理和zookeeper做负载均衡的分享就到这里,谢谢您的阅读,如果想了解更多关于ActiveMQ建立broker cluster实现负载均衡、Dubbo 与 Zookeeper、SpringMVC 整合和使用(负载均衡、容错)、dubbo负载均衡与服务降级以及Zookeeper认证、java使用zookeeper实现的分布式锁示例的相关信息,可以在本站进行搜索。
本文标签: