【使用Zookeeper当作注册中心】自己定制负载均衡常见策略

自己定制负载均衡常见策略

  • 一、前言
    • 随机(Random)策略的实现
    • 轮询(Round Robin)策略的实现
    • 哈希(Hash)策略

一、前言

大伙肯定知道,在分布式开发中,目前使用较多的注册中心有以下几个:

  1. Apache Zookeeper
  2. Netflix Eureka
  3. Alibaba Nacos

由于 Zookeeper 在面对高频次的服务注册和发现操作可能会一定的性能损耗等原因,搞得现在好多人都不用 Zookeeper 当做注册中心了。但它也提供了强一致性和高可靠性的特性,也没有被淘汰。

Zookeeper 本身并没有提供现成的服务发现功能,它更专注于分布式协调的能力。所以在使用 Zookeeper 作为注册中心时,需要自己在客户端实现服务的发现和负载均衡的逻辑。当然也可以去整合相关组件简化开发过程。

常见的负载均衡有以下三种:

  1. 随机(random)策略
  2. 轮询(round robin)策略
  3. 哈希(hash)策略

下面的话以寻注册中心的服务地址的需求来去对三种策略进行实现。

// 这是对应的策略接口
public interface RouteHandle {
			// 参数1:服务地址集合
			// 参数2:对应的key,我这里使用的是userId,这个结合自身项目需求
    String routeServer(List<String> values, String key);

}

随机(Random)策略的实现

/**
 * 随机的负载均衡
 */
public class RandomHandle implements RouteHandle {

    @Override
    public String routeServer(List<String> values, String key) {

        int size = values.size();

        if (size == 0) {
            throw new ApplicationException(UserErrorCode.SERVER_NOT_AVAILABLE);
        }
        // 去获取一个小于size的索引值
        // 你可以简单理解:随机整型数&size
        int index = ThreadLocalRandom.current().nextInt(size);
        return values.get(index);
    }
}

轮询(Round Robin)策略的实现

轮询策略即将请求次数和总的服务树取模,然后得出索引去得到服务信息。

/**
 * 轮询策略
 */
public class LoopHandle implements RouteHandle {

    private AtomicLong index = new AtomicLong();

    @Override
    public String routeServer(List<String> values, String key) {

        int size = values.size();
        if (size == 0) {
            throw new ApplicationException(UserErrorCode.SERVER_NOT_AVAILABLE);
        }

        Long l = index.incrementAndGet() % size;
        if (l < 0) {
            index.set(0L);
            l = 0L;
        }

        return values.get(l.intValue());
    }
}

哈希(Hash)策略

这里指的 Hash 策略一般指的是一次性 Hash 算法实现的策略。传统的 hash 在添加或删除一个节点的时候,会出现缓存失效,失效缓存比例为:m/(m+1);传统hash一般是将资源的 hashcode % table.size()(服务数)得到节点索引然后将访问服务,这样的话当增加一个节点的时候,除了hashcode为1的时候其对应的服务不变其他都缓存失效(0就不算它了,近似的一个值吧)也就是近于缓存失效比例为 m/m+1。

传统的hash造成的缓存失效很容易就把服务给搞蹦了,因为有大量资源访问不到的请求嘛。

然后就有了一致性hash算法,它将映射集合规定为0~2^32-1的范围的环,首尾相连。

在这里插入图片描述将节点放到(注册到)环中,然后根据资源的hash去顺时针寻其节点服务。

注意:当注册节点的时候,也有可能会出现hash偏斜问题,即节点都被放到了环的一边,使得资源大部分都使用的是俩边的节点,这个时候我们需要将每个服务节点设置一些虚拟节点注册到环上,这样的话每个服务节点近似均衡的分配给资源了。

在这里插入图片描述这里参考的文献:

一致性hash算法讲解——Java实现

下面对 hash 策略进行实现,下面是使用 TreeMap 对一次性hash算法进行实现的,这是因为它底层是使用 红黑树 进行实现的,有序,且添加起来比起平衡二叉树这样的不用老左旋右旋。主要是因为有序,对闭环的顺时针有序选节点是一致的,所以用 TreeMap 实现它比较多。当然也可以自身定义策略去实现。

/**
 * 使用 TreeMap 实现一致性hash
 */
public class TreeMapConsistentHash extends AbstractConsistentHash {

    private TreeMap<Long, String> treeMap = new TreeMap<>();

    private static final int NODE_SIZE = 2;  // 每个节点再注册虚拟节点的数量

    @Override
    protected void add(long key, String value) {
        for (int i = 0; i < NODE_SIZE; i++) {
            treeMap.put(super.hash("node" + key + i), value);
        }
        treeMap.put(key, value);
    }

    @Override
    protected String getFirstNodeValue(String value) {

        Long hash = super.hash(value);
        SortedMap<Long, String> last = treeMap.tailMap(hash);
        if(!last.isEmpty()){
            return last.get(last.firstKey());
        }

        if(treeMap.size() == 0){
            throw new ApplicationException(UserErrorCode.SERVER_NOT_AVAILABLE);
        }

        return treeMap.firstEntry().getValue();
    }

    @Override
    protected void processBefore() {
        treeMap.clear(); // 清空是因为,可能出现添加或删除服务的现象
    }
}

重点就是 addgetFirstNodeValue 方法,至于父类其他方法的实现不影响理解这个策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/83315.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

iOS代码混淆

文章目录 一、混淆的原理二、实现混淆1. 创建文件2. 将文件拖导入目录中3. 将以下脚本拷贝到刚新建的confuse.sh文件中4. 修改文件权限5. 修改项目配置6. 添加需要混淆的方法名7. 配置PCH文件8. 运行效果 一、混淆的原理 这里使用的混淆的原理是&#xff0c;用一串随机生成的字…

发展全球电商业务,为什么首选Facebook Messenger电子商务?

Facebook Messenger电子商务就是使用Facebook的消息传递渠道Messenger来购买和销售产品或服务。通过将 Messenger与客户服务平台&#xff0c;例如SaleSmartly&#xff08;SS客服&#xff09;集成&#xff0c;企业可以利用渠道强大的消息传递功能为客户提供更加个性化和对话式的…

ComPDFKit PDF SDK for Windows Crack

ComPDFKit PDF SDK for Windows Crack 添加了在创建文本框时调整默认属性的支持。 增加了对调整PDF大小时调整宽度的支持。 添加了对编辑文本时更多快捷方式的支持。 优化了文本输入&#xff0c;并将字体样式与原始文本相匹配。 在内容编辑器模式下复制和粘贴时优化了UI交互。 …

提升研发效能的开发工具

一、前言 随着企业对创新和效率的追求不断升级&#xff0c;研发效能成为了炙手可热的概念。各大公司纷纷成立专门的团队&#xff0c;以提升研发效能为重要目标。本文将从研发人员的视角出发&#xff0c;结合自身的深度思考&#xff0c;探讨研发效能的相关概念&#xff0c;共同寻…

Django的模型

定义模型 from django.db import models class User(models.Model):# 类属性是表示表的字段username models.CharField(max_length50,uniqueTrue)password models.CharField(max_length200)create_time models.DateTimeField(auto_now_addTrue) # auto_now_add新增数据时间…

Const的区别 学习笔记

C程序设计之const八大用法_哔哩哔哩_bilibili const优先修饰const左边&#xff0c;若左边没有东西&#xff0c;则修饰右边的东西 前两个a,b不是指针由于修饰的是int&#xff0c;是类型&#xff0c;所以a和b的值不能改变 c的类型的指针&#xff0c;const修饰的是int&#xff0…

DSO 系列文章(3)——DSO后端正规方程构造与Schur消元

文章目录 DSO代码注释&#xff1a;https://github.com/Cc19245/DSO-CC_Comments

Unittest+Selenium模块驱动自动化测试实战

UnittestSelenium自动化测试框架使用模块驱动测试模型将冗余的代码封装成类&#xff0c;且基于PageObject的自动化设计模式&#xff0c;通过分层的方式将页面对象、操作、业务分开处理。 1、首先创建自动化测试框架的文件模块架构&#xff0c;创建common、base、testcase、rep…

PHP服饰文化网站系统Dreamweaver开发mysql数据库web结构php编程计算机网页项目

一、源码特点 PHP 服饰文化网站系统是一套完善的web设计系统&#xff0c;对理解php编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 源码下载 https://download.csdn.net/download/qq_41221322/88236778 PHP服饰文化网站…

天锐绿盾加密软件——「文件数据防泄密系统」

文件加密功能 采用透明加解密技术&#xff0c; 企业内部文件自动加密&#xff0c;内部正常使用&#xff0c;不改变使用习惯。加密后的文件未经许可&#xff0c;私自外发拷贝到公司以外&#xff0c;都将显示为乱码无法使用&#xff0c;从源头上保障核心数据安全。 产品跨平台支持…

Apinto 网关进阶教程,插件开发入门指南

Apinto 是基于Go语言&#xff0c;由 Eolink 自主研发的一款高性能、可扩展、易维护的云原生 API 网关。Apinto 能够帮助用户简单、快速、低成本、低风险地实现&#xff1a;系统微服务化、系统集成、向合作伙伴、开发者开放功能和数据。 通过 Apinto&#xff0c;企业能够专注于…

《HeadFirst设计模式(第二版)》第十一章代码——代理模式

代码文件目录&#xff1a; RMI&#xff1a; MyRemote package Chapter11_ProxyPattern.RMI;import java.rmi.Remote; import java.rmi.RemoteException;public interface MyRemote extends Remote {public String sayHello() throws RemoteException; }MyRemoteClient packa…

Aurora 8B/10B

目录 1. Overview2. Feature List2. Block Diagram3. PDU Transmission Procedure3.1. User InterfaceFraming InterfaceStreaming Interface 3.2. Clock Compensation3.3. Aurora 8B/10B Frame Gen3.4. 8B/10B Transmission Code 4. PDU Reception Procedure5. Flow Control5.…

构建 NodeJS 影院微服务并使用 docker 部署【01/4】

图片来自谷歌 — 封面由我制作 一、说明 构建一个微服务的电影网站&#xff0c;需要Docker、NodeJS、MongoDB&#xff0c;这样的案例您见过吗&#xff1f;如果对此有兴趣&#xff0c;您就继续往下看吧。 在本系列中&#xff0c;我们将构建一个 NodeJS 微服务&#xff0c;并使用…

React2023电商项目实战 - 1.项目搭建

古人学问无遗力&#xff0c;少壮工夫老始成。 纸上得来终觉浅&#xff0c;绝知此事要躬行。 —— 陆游《《冬夜读书示子聿》》 系列文章目录 项目搭建App登录及网关App文章自媒体平台&#xff08;博主后台&#xff09;内容审核(自动) 文章目录 系列文章目录一、项目介绍1.页面…

使用@antv/x6-vue-shape 遇到的问题

最近用antv/x6开发一个功能&#xff0c;遇到的坑太多了&#xff0c;心累啊。。。 想用官方提供的antv/x6-vue-shape &#xff0c;目的是使用vue组件创建画布元素。 官方文档&#xff1a; 链接&#xff1a;使用 HTML/React/Vue/Angular 渲染 | X6 使用npm install 安装 报错…

linux部署kafka3.5.1(单机)

一、下载jdk17 kafka3.x版本需要jdk11以上版本才能更好的兼容&#xff0c;jdk11、jdk17都是LTS长期维护版本&#xff0c;而且jdk17支持springboot3.x,所以我选择了openjdk17。 下载地址: Archived OpenJDK GA Releaseshttps://jdk.java.net/archive/ 二、上传jdk安装包解压 …

接口自动化yaml文件读取与写入

前言 在走进yaml文件之前大家应该都很想知道他是用来干嘛的&#xff1f; 是的是的&#xff0c;他是用来做接口自动化测试的。 我们一起来学习他吧&#xff01;——&#xff08;一定要收藏带走哦❤&#xff09; 1、yaml文件有什么作用呢&#xff1f; ①可作为配置文件使用—…

linux tomcat server.xml 项目访问路径变更不生效

如果想改成默认的127.0.0.1:8080 访问项目 先确定更改的作用文件 server.xml 的 host:appBase 标签 默认找到appBase webapps 下的war包&#xff0c;并解压&#xff0c;解压后的appname为访问路径 也就变成了 127.0.0.1:8080/appname host:Context:path 标签 appBase的 优先…

HTTP 握手过程

HTTP 握手过程 TCP 建立连接 3 次握手 客户端请求连接服务器服务器响应成功客户端回应服务器准备开始连接 TCP 结束连接 4 次挥手 客户端向服务器发送&#xff0c;断开请求服务器向客户端发送&#xff0c;还有数据没有传输完毕&#xff0c;请稍等服务器向客户端发送&#x…