当前位置: 首页 > news >正文

从零手写实现 nginx-32-load balance 负载均衡算法 java 实现

前言

大家好,我是老马。很高兴遇到你。

我们为 java 开发者实现了 java 版本的 nginx

https://github.com/houbb/nginx4j

如果你想知道 servlet 如何处理的,可以参考我的另一个项目:

手写从零实现简易版 tomcat minicat

手写 nginx 系列

如果你对 nginx 原理感兴趣,可以阅读:

从零手写实现 nginx-01-为什么不能有 java 版本的 nginx?

从零手写实现 nginx-02-nginx 的核心能力

从零手写实现 nginx-03-nginx 基于 Netty 实现

从零手写实现 nginx-04-基于 netty http 出入参优化处理

从零手写实现 nginx-05-MIME类型(Multipurpose Internet Mail Extensions,多用途互联网邮件扩展类型)

从零手写实现 nginx-06-文件夹自动索引

从零手写实现 nginx-07-大文件下载

从零手写实现 nginx-08-范围查询

从零手写实现 nginx-09-文件压缩

从零手写实现 nginx-10-sendfile 零拷贝

从零手写实现 nginx-11-file+range 合并

从零手写实现 nginx-12-keep-alive 连接复用

从零手写实现 nginx-13-nginx.conf 配置文件介绍

从零手写实现 nginx-14-nginx.conf 和 hocon 格式有关系吗?

从零手写实现 nginx-15-nginx.conf 如何通过 java 解析处理?

从零手写实现 nginx-16-nginx 支持配置多个 server

从零手写实现 nginx-17-nginx 默认配置优化

从零手写实现 nginx-18-nginx 请求头+响应头操作

从零手写实现 nginx-19-nginx cors

从零手写实现 nginx-20-nginx 占位符 placeholder

从零手写实现 nginx-21-nginx modules 模块信息概览

从零手写实现 nginx-22-nginx modules 分模块加载优化

从零手写实现 nginx-23-nginx cookie 的操作处理

从零手写实现 nginx-24-nginx IF 指令

从零手写实现 nginx-25-nginx map 指令

从零手写实现 nginx-26-nginx rewrite 指令

从零手写实现 nginx-27-nginx return 指令

从零手写实现 nginx-28-nginx error_pages 指令

从零手写实现 nginx-29-nginx try_files 指令

从零手写实现 nginx-30-nginx proxy_pass upstream 指令

从零手写实现 nginx-31-nginx load-balance 负载均衡

从零手写实现 nginx-32-nginx load-balance 算法 java 实现

nginx 支持哪几种负载均衡算法?

Nginx 支持以下几种主要的负载均衡算法:

  1. 轮询(Round Robin)

    • 默认的负载均衡算法,请求依次分配给每个后端服务器。
  2. 权重轮询(Weighted Round Robin)

    • 基于权重进行轮询,权重越高的服务器分配的请求越多。
  3. 最少连接(Least Connections)

    • 新请求分配给当前活动连接数最少的服务器。
  4. IP 哈希(IP Hash)

    • 根据客户端的 IP 地址分配请求,确保相同 IP 地址的请求分配到同一台服务器上。
  5. 一致性哈希(Hash)

    • 根据用户定义的键(如 URL、cookie 等)分配请求,确保相同键的请求分配到同一台服务器上。

示例配置

1. 轮询(Round Robin)
upstream my_backend {server 192.168.0.1;server 192.168.0.2;server 192.168.0.3;
}server {listen 80;server_name www.example.com;location / {proxy_pass http://my_backend;}
}
2. 权重轮询(Weighted Round Robin)
upstream my_backend {server 192.168.0.1 weight=3;server 192.168.0.2 weight=2;server 192.168.0.3 weight=1;
}server {listen 80;server_name www.example.com;location / {proxy_pass http://my_backend;}
}
3. 最少连接(Least Connections)
upstream my_backend {least_conn;server 192.168.0.1;server 192.168.0.2;server 192.168.0.3;
}server {listen 80;server_name www.example.com;location / {proxy_pass http://my_backend;}
}
4. IP 哈希(IP Hash)
upstream my_backend {ip_hash;server 192.168.0.1;server 192.168.0.2;server 192.168.0.3;
}server {listen 80;server_name www.example.com;location / {proxy_pass http://my_backend;}
}
5. 一致性哈希(Hash)
upstream my_backend {hash $request_uri;server 192.168.0.1;server 192.168.0.2;server 192.168.0.3;
}server {listen 80;server_name www.example.com;location / {proxy_pass http://my_backend;}
}

总结

Nginx 支持多种负载均衡算法,包括轮询、权重轮询、最少连接、IP 哈希和一致性哈希。

每种算法适用于不同的场景,可以根据具体需求选择合适的算法来优化负载均衡策略。

java 实现

轮询算法(Round Robin)

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;public class RoundRobinLoadBalancer {private List<String> servers;private AtomicInteger currentIndex;public RoundRobinLoadBalancer(List<String> servers) {this.servers = servers;this.currentIndex = new AtomicInteger(0);}public String getNextServer() {int index = currentIndex.getAndUpdate(i -> (i + 1) % servers.size());return servers.get(index);}public static void main(String[] args) {List<String> servers = List.of("192.168.0.1", "192.168.0.2", "192.168.0.3");RoundRobinLoadBalancer loadBalancer = new RoundRobinLoadBalancer(servers);// 模拟10次请求for (int i = 0; i < 10; i++) {String server = loadBalancer.getNextServer();System.out.println("Redirecting request to: " + server);}}
}

java 如何实现权重轮询算法?

实现权重轮询算法(Weighted Round Robin)可以根据每个服务器的权重来分配请求,权重越高的服务器接收的请求越多。

import java.util.ArrayList;
import java.util.List;class Server {String ip;int weight;Server(String ip, int weight) {this.ip = ip;this.weight = weight;}
}public class WeightedRoundRobinLoadBalancer {private List<Server> servers;private List<String> weightedServerList;private int currentIndex;public WeightedRoundRobinLoadBalancer(List<Server> servers) {this.servers = servers;this.weightedServerList = new ArrayList<>();this.currentIndex = 0;// 根据服务器的权重初始化加权后的服务器列表for (Server server : servers) {for (int i = 0; i < server.weight; i++) {weightedServerList.add(server.ip);}}}public String getNextServer() {if (weightedServerList.isEmpty()) {throw new IllegalStateException("No servers available");}String server = weightedServerList.get(currentIndex);currentIndex = (currentIndex + 1) % weightedServerList.size();return server;}public static void main(String[] args) {List<Server> servers = List.of(new Server("192.168.0.1", 3), // 权重为3new Server("192.168.0.2", 2), // 权重为2new Server("192.168.0.3", 1)  // 权重为1);WeightedRoundRobinLoadBalancer loadBalancer = new WeightedRoundRobinLoadBalancer(servers);// 模拟10次请求for (int i = 0; i < 10; i++) {String server = loadBalancer.getNextServer();System.out.println("Redirecting request to: " + server);}}
}

java 如何实现最少连接算法?具体实现

最少连接算法(Least Connections)是一种负载均衡算法,它将请求分配给当前活动连接数最少的服务器。

在 Java 中实现这个算法,需要跟踪每个服务器的当前连接数,并在每次请求时选择连接数最少的服务器。

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;class Server {String ip;AtomicInteger activeConnections;Server(String ip) {this.ip = ip;this.activeConnections = new AtomicInteger(0);}
}public class LeastConnectionsLoadBalancer {private List<Server> servers;public LeastConnectionsLoadBalancer(List<Server> servers) {this.servers = servers;}public Server getNextServer() {if (servers.isEmpty()) {throw new IllegalStateException("No servers available");}Server leastConnectedServer = servers.get(0);for (Server server : servers) {if (server.activeConnections.get() < leastConnectedServer.activeConnections.get()) {leastConnectedServer = server;}}leastConnectedServer.activeConnections.incrementAndGet();return leastConnectedServer;}public void releaseConnection(Server server) {server.activeConnections.decrementAndGet();}public static void main(String[] args) {List<Server> servers = List.of(new Server("192.168.0.1"),new Server("192.168.0.2"),new Server("192.168.0.3"));LeastConnectionsLoadBalancer loadBalancer = new LeastConnectionsLoadBalancer(servers);// 模拟10次请求for (int i = 0; i < 10; i++) {Server server = loadBalancer.getNextServer();System.out.println("Redirecting request to: " + server.ip);// 模拟处理完成后释放连接loadBalancer.releaseConnection(server);}}
}

java 如何实现 IP 哈希算法?具体实现

IP 哈希算法(IP Hash)是一种负载均衡算法,它根据客户端的 IP 地址分配请求,确保同一 IP 地址的请求始终分配到同一台服务器。

这样可以实现会话保持(session persistence)。

import java.util.List;
import java.util.Objects;class Server {String ip;Server(String ip) {this.ip = ip;}
}public class IPHashLoadBalancer {private List<Server> servers;public IPHashLoadBalancer(List<Server> servers) {this.servers = servers;}public Server getServer(String clientIP) {if (servers.isEmpty()) {throw new IllegalStateException("No servers available");}int hash = Math.abs(Objects.hash(clientIP));int serverIndex = hash % servers.size();return servers.get(serverIndex);}public static void main(String[] args) {List<Server> servers = List.of(new Server("192.168.0.1"),new Server("192.168.0.2"),new Server("192.168.0.3"));IPHashLoadBalancer loadBalancer = new IPHashLoadBalancer(servers);// 模拟请求String[] clientIPs = {"192.168.1.10", "192.168.1.20", "192.168.1.30","192.168.1.40", "192.168.1.50", "192.168.1.60"};for (String clientIP : clientIPs) {Server server = loadBalancer.getServer(clientIP);System.out.println("Client IP: " + clientIP + " is routed to server: " + server.ip);}}
}

java 如何实现一致性哈希算法

一致性哈希算法是一种常见的负载均衡算法,可以实现请求在服务器间的均匀分布,并且在增加或减少服务器时只影响少量请求的映射。

下面是一个基于 Java 的一致性哈希算法的实现。

import java.util.SortedMap;
import java.util.TreeMap;class Server {String ip;Server(String ip) {this.ip = ip;}@Overridepublic String toString() {return ip;}
}public class ConsistentHashingLoadBalancer {private final SortedMap<Integer, Server> circle = new TreeMap<>();private final int numberOfReplicas;public ConsistentHashingLoadBalancer(List<Server> servers, int numberOfReplicas) {this.numberOfReplicas = numberOfReplicas;for (Server server : servers) {add(server);}}private void add(Server server) {for (int i = 0; i < numberOfReplicas; i++) {int hash = hash(server.ip + i);circle.put(hash, server);}}public void remove(Server server) {for (int i = 0; i < numberOfReplicas; i++) {int hash = hash(server.ip + i);circle.remove(hash);}}public Server getServer(String key) {if (circle.isEmpty()) {return null;}int hash = hash(key);if (!circle.containsKey(hash)) {SortedMap<Integer, Server> tailMap = circle.tailMap(hash);hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();}return circle.get(hash);}private int hash(String key) {return key.hashCode() & 0x7fffffff; // 保证正数}public static void main(String[] args) {List<Server> servers = List.of(new Server("192.168.0.1"),new Server("192.168.0.2"),new Server("192.168.0.3"));ConsistentHashingLoadBalancer loadBalancer = new ConsistentHashingLoadBalancer(servers, 3);// 模拟请求String[] clientKeys = {"client1", "client2", "client3","client4", "client5", "client6"};for (String key : clientKeys) {Server server = loadBalancer.getServer(key);System.out.println("Client key: " + key + " is routed to server: " + server);}// 增加一个服务器System.out.println("\nAdding a new server 192.168.0.4\n");loadBalancer.add(new Server("192.168.0.4"));for (String key : clientKeys) {Server server = loadBalancer.getServer(key);System.out.println("Client key: " + key + " is routed to server: " + server);}// 移除一个服务器System.out.println("\nRemoving a server 192.168.0.2\n");loadBalancer.remove(new Server("192.168.0.2"));for (String key : clientKeys) {Server server = loadBalancer.getServer(key);System.out.println("Client key: " + key + " is routed to server: " + server);}}
}

相关文章:

从零手写实现 nginx-32-load balance 负载均衡算法 java 实现

前言 大家好&#xff0c;我是老马。很高兴遇到你。 我们为 java 开发者实现了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何处理的&#xff0c;可以参考我的另一个项目&#xff1a; 手写从零实现简易版 tomcat minicat 手写 nginx 系列 …...

基于STC89C51单片机的烟雾报警器设计(煤气火灾检测报警)(含文档、源码与proteus仿真,以及系统详细介绍)

本篇文章论述的是基于STC89C51单片机的烟雾报警器设计的详情介绍&#xff0c;如果对您有帮助的话&#xff0c;还请关注一下哦&#xff0c;如果有资源方面的需要可以联系我。 目录 摘要 原理图 实物图 仿真图 元件清单 代码 系统论文 资源下载 摘要 随着现代家庭用火、…...

SpringBoot整合阿里云RocketMQ对接,商业版

1.需要阿里云开通商业版RocketMQ 普通消息新建普通主题,普通组,延迟消息新建延迟消息主题,延迟消息组 2.结构目录 3.引入依赖 <!--阿里云RocketMq整合--><dependency><groupId>com.aliyun.openservices</groupId><artifactId>ons-client</…...

modbus slave 设备通过 网关thingsboard-gateway 将数据上传到thingsboard云平台

搭建thingsboard物联网云平台花了大量时间&#xff0c;从小白到最后搭建成功&#xff0c;折磨了好几天&#xff0c;也感谢网友的帮助&#xff0c;提供了思路最终成功搞定&#xff0c;特此记录。 一、thingsboard环境搭建&#xff08;Ubuntu20.04LTS&#xff09; 参考官方文档&a…...

安全防御:智能选路

目录 一、智能选路 1.1 就近选路 1.2 策略路由 1.3 虚拟系统---VRF 二、全局选路策略 1&#xff0c;基于链路带宽进行负载分担 2&#xff0c;基于链路质量进行负载分担 3&#xff0c;基于链路权重的负载分担 4&#xff0c;根据链路优先级的主备备份 DNS透明代理 一、…...

Gitee使用教程2-克隆仓库(下载项目)并推送更新项目

一、下载 Gitee 仓库 1、点击克隆-复制代码 2、打开Git Bash 并输入复制的代码 下载好后&#xff0c;找不到文件在哪的可以输入 pwd 找到仓库路径 二、推送更新 Gitee 项目 1、打开 Git Bash 用 cd 命令进入你的仓库&#xff08;我的仓库名为book&#xff09; 2、添加文件到 …...

Postfix+Dovecot+Roundcube开源邮件系统搭建系列1-2:系统搭建目标+MariaDB数据库配置(MySQL)

1. 系统搭建目标 通过本系列文章&#xff0c;最终可以部署一套提供如下服务的邮件系统&#xff1a; SMTP服务&#xff1a;由Postfix提供&#xff0c;监听25、465、587端口。POP3服务&#xff1a;由Dovecot提供&#xff0c;监听110、995端口。IMAP服务&#xff1a;由Dovecot提…...

Flower花所比特币交易及交易费用科普

在加密货币交易中&#xff0c;选择一个可靠的平台至关重要。Flower花所通过提供比特币交易服务脱颖而出。本文将介绍在Flower花所进行比特币交易的基础知识及其交易费用。 什么是Flower花所&#xff1f; Flower花所是一家加密货币交易平台&#xff0c;为新手和资深交易者提供…...

1个Xpath定位可以在Web页面查找到多个元素Selenium

1个Xpath定位可以在Web页面查找到多个元素Selenium//input[id\"transactionId\"] 打开Web页面&#xff0c; 点击F12可以看到压面 点击Ctrl F 可以点图如下图的输入框&#xff0c;输入xpath&#xff0c;看右侧可以找到3个对应的元素 点击Ctrl F 点击Ctrl F 点…...

智慧博物馆的“眼睛”:视频智能监控技术守护文物安全与智能化管理

近日&#xff0c;位于四川德阳的三星堆博物馆迎来了参观热潮。据新闻报道&#xff0c;三星堆博物馆的日均参观量达1.5万人次。随着暑假旅游高峰期的到来&#xff0c;博物馆作为重要的文化场所&#xff0c;也迎来了大量游客。博物馆作为文化和历史的重要载体&#xff0c;其安全保…...

vue中:class、watch、v-show使用

1、:class 指令 在 Vue.js 中&#xff0c;:class 指令&#xff08;或 v-bind:class&#xff09;允许你动态地绑定 CSS 类到一个元素。这个指令有两种主要的使用方式&#xff1a;绑定一个对象或者绑定一个数组。 1.1、:class{} 对象语法 对象语法允许你基于条件来添加或移除类…...

中电金信-杭州工商银行|面试真题|2024年

中电金信-杭州工商银行 JAva集合用过哪些? ArrayList、LinkedList、HashSet、TreeSet、HashMap、LinkedHashMap、ConcurrentHashMap Arraylist和linkbist区别 ArrayList底层是数据&#xff0c;查询快&#xff0c;增删慢&#xff0c;线程不安全&#xff0c;效率高LikedList 底…...

搞定前端面试题——ES6同步与异步机制、async/await的使用以及Promise的使用!!!

文章目录 同步和异步async/awaitPromisePromise的概念 同步和异步 ​ 同步&#xff1a;代码按照编写顺序逐行执行&#xff0c;后续的代码必须等待当前正在执行的代码完成之后才能执行&#xff0c;当遇到耗时的操作&#xff08;如网络请求等&#xff09;时&#xff0c;主线程会…...

Redis数据结构--跳跃表 Skip List

跳跃表&#xff08;Skip List&#xff09;是一种高效的随机化数据结构&#xff0c;通过引入多层索引来实现快速的查找、插入和删除操作。它在Redis中被用来实现有序集合&#xff08;Sorted Set&#xff09;&#xff0c;在处理大量数据时表现出了优越的性能和灵活性。本文将详细…...

线状激光模组定制厂家哪家好?具体怎么收费?

在激光技术领域&#xff0c;线状激光模组因其高精度、高效率的特点&#xff0c;被广泛应用于工业制造、科研实验及医疗设备等多个领域。然而&#xff0c;市场上的线状激光模组种类繁多&#xff0c;品质参差不齐。然后如何选择线状激光模组定制厂家&#xff0c;以及了解其具体收…...

【Python游戏】编程开发贪吃蛇游戏(第一期)

本文收录于 《一起学Python趣味编程》专栏&#xff0c;从零基础开始&#xff0c;分享一些Python编程知识&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、贪吃蛇游戏开发简介2.1 贪吃蛇游戏规则2.2 贪吃蛇游戏开发步骤 三、贪吃蛇游戏开发实战四、总结…...

【机器学习入门】拥抱人工智能,从机器学习开始

拥抱人工智能&#xff0c;从机器学习开始 目录&#xff1a; 1. 机器学习&#xff1a;一种实现人工智能的方法 2. 机器学习算法&#xff1a;是使计算机具有智能的关键 3. Anaconda&#xff1a;初学Python、入门机器学习的首选 4. 总结 转载链接&#xff1a; 文章-阿里云开发者社…...

【React打卡学习第一天】

React入门 一、简介二、基本使用1.引入相关js库2.babel.js的作用 二、创建虚拟DOM三、JSX&#xff08;JavaScript XML&#xff09;1.本质2.作用3.基本语法规则定义虚拟DOM时&#xff0c;不要写引号。标签中混入JS表达式时要用{}。样式的类名指定不要用class,要用className.内联…...

matlab PID tuner整定工具箱的用法

从主页的APP中搜索到它&#xff1a; 按照下图IMPORT导入被控对象的传递函数 在下图的Inspect按钮中可以看到导入的被控对象的传函。 在下图的Type中选择控制器类型&#xff1a; 在下图的Form中选择PID的形式&#xff1a;有两种可选&#xff1a;平行式Parallel和标准式Standard …...

富格林:可信办法阻挠虚假受骗

富格林悉知&#xff0c;在现货黄金中&#xff0c;投资者一定要谦虚谨慎切记不要骄傲自大&#xff0c;否则就可能遭遇投资虚假受骗。在盈利后一定要持续学习可信技巧稳固基础&#xff0c;失败了一定要总结错误教训这样才能阻挠虚假受骗为以后的稳定盈利打好基础。以下是富格林总…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

多场景 OkHttpClient 管理器 - Android 网络通信解决方案

下面是一个完整的 Android 实现&#xff0c;展示如何创建和管理多个 OkHttpClient 实例&#xff0c;分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

JS手写代码篇----使用Promise封装AJAX请求

15、使用Promise封装AJAX请求 promise就有reject和resolve了&#xff0c;就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”

案例&#xff1a; 某医药分销企业&#xff0c;主要经营各类药品的批发与零售。由于药品的特殊性&#xff0c;效期管理至关重要&#xff0c;但该企业一直面临效期问题的困扰。在未使用WMS系统之前&#xff0c;其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...

[特殊字符] 手撸 Redis 互斥锁那些坑

&#x1f4d6; 手撸 Redis 互斥锁那些坑 最近搞业务遇到高并发下同一个 key 的互斥操作&#xff0c;想实现分布式环境下的互斥锁。于是私下顺手手撸了个基于 Redis 的简单互斥锁&#xff0c;也顺便跟 Redisson 的 RLock 机制对比了下&#xff0c;记录一波&#xff0c;别踩我踩过…...