Java는 여러 로드 밸런싱 알고리즘을 구현합니다.
먼저 로드 밸런싱이 무엇인지 소개하겠습니다(백과사전에서 발췌)
로드 밸런싱은 기존 네트워크 구조를 활용하여 네트워크 장치와 서버의 대역폭을 확장하고, 처리량을 늘리며, 네트워크 데이터 처리 기능을 강화하고, 네트워크 유연성과 가용성을 향상시키는 저렴하고 효과적이며 투명한 방법을 제공합니다.
로드 밸런싱, 영어 이름은 Load Balance입니다. 이는 웹 서버, FTP 서버, 기업 키 애플리케이션 서버 및 기타 미션 크리티컬 서버 등과 같은 여러 운영 단위에 실행을 할당한다는 의미입니다. 함께 작업을 완료합니다.
이번 글에서는 "외부에서 특정 서버로 보내는 요청을 대칭 구조로 균등하게 분배"하기 위한 다양한 알고리즘에 대해 이야기하고, 각 알고리즘의 구체적인 구현을 Java 코드로 보여드리겠습니다. 본 주제에 들어가기 전에 먼저 IP 목록을 시뮬레이션하는 클래스를 작성하세요.
import java.util.HashMap; /** * @author [email protected] * @date 二月 07, 2017 */ public class IpMap { // 待路由的Ip列表,Key代表Ip,Value代表该Ip的权重 public static HashMap<String, Integer> serverWeightMap = new HashMap<String, Integer>(); static { serverWeightMap.put("192.168.1.100", 1); serverWeightMap.put("192.168.1.101", 1); // 权重为4 serverWeightMap.put("192.168.1.102", 4); serverWeightMap.put("192.168.1.103", 1); serverWeightMap.put("192.168.1.104", 1); // 权重为3 serverWeightMap.put("192.168.1.105", 3); serverWeightMap.put("192.168.1.106", 1); // 权重为2 serverWeightMap.put("192.168.1.107", 2); serverWeightMap.put("192.168.1.108", 1); serverWeightMap.put("192.168.1.109", 1); serverWeightMap.put("192.168.1.110", 1); } }
라운드 로빈 방식
라운드 로빈 스케줄링 알고리즘의 원리는 IP 목록에서 IP 주소를 보내는 것입니다. 매번 사용자 요청은 1부터 시작하여 N(내부 서버 수)까지 차례로 내부 서버에 할당되고 주기 가 다시 시작됩니다. 알고리즘의 장점은 단순성입니다. 모든 현재 연결 상태를 기록할 필요가 없으므로 상태 비저장 스케줄링입니다.
코드 구현은 대략 다음과 같습니다.
import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * @author [email protected] * @date 二月 07, 2017 */ class RoundRobin { private static Integer pos = 0; public static String getServer() { // 重建一个Map,避免服务器的上下线导致的并发问题 Map<String, Integer> serverMap = new HashMap<String, Integer>(); serverMap.putAll(IpMap.serverWeightMap); // 取得Ip地址List Set keySet = serverMap.keySet(); ArrayList keyList = new ArrayList(); keyList.addAll(keySet); String server = null; synchronized (pos) { if (pos > keySet.size()) pos = 0; server = keyList.get(pos); pos ++; } return server; } }
serverWeightMap의 주소 목록은 동적이므로 머신은 언제든지 온라인, 오프라인 또는 다운될 수 있습니다. 가능한 동시성 문제를 피하려면 메서드 내에서 새 로컬 변수 serverMap을 생성해야 합니다. 이제 여러 스레드에 의해 수정되는 것을 방지하기 위해 serverMap의 내용을 스레드 로컬에 복사합니다. 이로 인해 새로운 문제가 발생할 수 있습니다. 복제 후 serverWeightMap에 대한 수정 사항은 serverMap에 반영되지 않습니다. 즉, 이 서버 선택 중에 로드 밸런싱 알고리즘은 새 서버가 추가되었는지 오프라인 서버가 추가되었는지 알 수 없습니다. 서버를 새로 추가해도 상관없습니다. 서버가 오프라인 상태가 되거나 충돌이 발생하면 존재하지 않는 주소에 액세스할 수도 있습니다. 따라서 서비스 호출자는 서버 선택 및 호출을 다시 시작하는 등 해당 내결함성 처리를 수행해야 합니다.
현재 폴링된 위치 변수 pos의 경우 서버 선택 순서를 보장하기 위해 작업 중에 하나의 스레드만 동시에 pos 값을 수정할 수 있도록 잠가야 합니다. pos 변수를 동시에 수정하는 경우 서버 선택 순서를 보장할 수 없으며, keyList 배열이 범위를 벗어날 수도 있습니다.
폴링 방식의 장점은 요청 전송에서 절대적인 균형을 이루려고 한다는 것입니다.
폴링 방식의 단점은 요청 전송의 절대적인 균형을 이루기 위해서는 상당한 비용을 지불해야 한다는 것입니다. 왜냐하면 pos 변수 수정의 상호 배제를 보장하기 위해 무거운 비관적 잠금 동기화 이는 이 폴링 코드의 동시 처리량을 크게 떨어뜨립니다.
랜덤(Random)방식
시스템의 랜덤 알고리즘을 통해 백엔드 서버의 리스트 사이즈 값을 기준으로 서버 중 하나를 랜덤하게 선택하여 접속하게 됩니다. 클라이언트가 서버를 호출하는 횟수가 증가할수록
실제 효과는 백엔드에서 각 서버에 대한 호출을 균등하게 분배하는 것에 점점 가까워진다는 것을 확률과 통계 이론으로 알 수 있으며, 이는 폴링의 결과입니다.
Random 메서드의 코드 구현은 대략 다음과 같습니다.
import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * @author [email protected] * @date 二月 07, 2017 */ class Random { public static String getServer() { // 重建一个Map,避免服务器的上下线导致的并发问题 Map<String, Integer> serverMap = new HashMap<String, Integer>(); serverMap.putAll(IpMap.serverWeightMap); // 取得Ip地址List Set keySet = serverMap.keySet(); ArrayList keyList = new ArrayList(); keyList.addAll(keySet); java.util.Random random = new java.util.Random(); int randomPos = random.nextInt(keyList.size()); return keyList.get(randomPos); } }
전체적인 코드 아이디어는 폴링 메서드와 일치합니다. 먼저 serverMap을 다시 빌드한 다음 서버 목록을 가져옵니다. 서버를 선택할 때 Random의 nextInt 메소드를 사용하여 0~keyList.size() 범위의 임의의 값을 가져와서 서버 목록에서 서버 주소를 무작위로 얻어서 반환합니다. 확률 통계 이론에 따르면 처리량이 많을수록 무작위 알고리즘의 효과는 폴링 알고리즘의 효과에 더 가깝습니다.
소스 주소 해시(Hash) 방법
소스 주소 해시의 개념은 클라이언트의 IP 주소를 기반으로 해시 함수를 통해 계산된 값을 구하고, 이 값을 사용하는 것입니다. 서버 목록을 비교하려면 크기에 대해 모듈로 연산을 수행하고 그 결과는 클라이언트가 서버에 액세스하려는 일련 번호입니다. 소스 주소 해시 방법은 로드 밸런싱에 사용됩니다. 백엔드 서버 목록이 변경되지 않은 경우 동일한 IP 주소를 가진 클라이언트는 매번 동일한 백엔드 서버에 매핑됩니다.
소스 주소 해시 알고리즘의 코드 구현은 대략 다음과 같습니다.
import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Set; /** * @author [email protected] * @date 二月 07, 2017 */ class Hash { public static String getServer() { // 重建一个Map,避免服务器的上下线导致的并发问题 Map<String, Integer> serverMap = new HashMap<String, Integer>(); serverMap.putAll(IpMap.serverWeightMap); // 取得Ip地址List Set keySet = serverMap.keySet(); ArrayList keyList = new ArrayList(); keyList.addAll(keySet); // 在Web应用中可通过HttpServlet的getRemoteIp方法获取 String remoteIp = "127.0.0.1"; int hashCode = remoteIp.hashCode(); int serverListSize = keyList.size(); int serverPos = hashCode % serverListSize; return keyList.get(serverPos); } }
처음 두 부분은 폴링 방식과 동일하며, 차이점은 라우팅 부분에 있습니다. . 클라이언트의 IP(remoteIp)를 통해 해당 해시 값을 얻고 서버 목록의 크기를 모듈로로 구합니다. 결과는 서버 목록에서 선택한 서버의 index 값입니다.
소스 주소 해싱의 장점은 백엔드 서버 목록이 변경될 때까지 동일한 클라이언트 IP 주소가 동일한 백엔드 서버로 해싱된다는 것입니다. 이 기능에 따르면 서비스 소비자와 서비스 제공자 간에 상태 저장 세션이 설정될 수 있습니다.
源地址哈希算法的缺点在于:除非集群中服务器的非常稳定,基本不会上下线,否则一旦有服务器上线、下线,那么通过源地址哈希算法路由到的服务器是服务器上线、下线前路由到的服务器的概率非常低,如果是session则取不到session,如果是缓存则可能引发"雪崩"。如果这么解释不适合明白,可以看我之前的一篇文章MemCache超详细解读,一致性Hash算法部分。
加权轮询(Weight Round Robin)法
不同的后端服务器可能机器的配置和当前系统的负载并不相同,因此它们的抗压能力也不相同。给配置高、负载低的机器配置更高的权重,让其处理更多的请;而配置低、负载高的机器,给其分配较低的权重,降低其系统负载,加权轮询能很好地处理这一问题,并将请求顺序且按照权重分配到后端。加权轮询法的代码实现大致如下:
import java.util.*; /** * @author [email protected] * @date 二月 07, 2017 */ class WeightRoundRobin { private static Integer pos; public static String getServer() { // 重建一个Map,避免服务器的上下线导致的并发问题 Map<String, Integer> serverMap = new HashMap<String, Integer>(); serverMap.putAll(IpMap.serverWeightMap); // 取得Ip地址List Set keySet = serverMap.keySet(); Iterator iterator = keySet.iterator(); List serverList = new ArrayList(); while (iterator.hasNext()) { String server = iterator.next(); int weight = serverMap.get(server); for (int i = 0; i < weight; i++) serverList.add(server); } String server = null; synchronized (pos) { if (pos > keySet.size()) pos = 0; server = serverList.get(pos); pos ++; } return server; } }
与轮询法类似,只是在获取服务器地址之前增加了一段权重计算的代码,根据权重的大小,将地址重复地增加到服务器地址列表中,权重越大,该服务器每轮所获得的请求数量越多。
加权随机(Weight Random)法
与加权轮询法一样,加权随机法也根据后端机器的配置,系统的负载分配不同的权重。不同的是,它是按照权重随机请求后端服务器,而非顺序。
import java.util.*; /** * @author [email protected] * @date 二月 07, 2017 */ class WeightRandom { public static String getServer() { // 重建一个Map,避免服务器的上下线导致的并发问题 Map<String, Integer> serverMap = new HashMap<String, Integer>(); serverMap.putAll(IpMap.serverWeightMap); // 取得Ip地址List Set keySet = serverMap.keySet(); Iterator iterator = keySet.iterator(); List serverList = new ArrayList(); while (iterator.hasNext()) { String server = iterator.next(); int weight = serverMap.get(server); for (int i = 0; i < weight; i++) serverList.add(server); } java.util.Random random = new java.util.Random(); int randomPos = random.nextInt(serverList.size()); return serverList.get(randomPos); } }
这段代码相当于是随机法和加权轮询法的结合,比较好理解,就不解释了。
最小连接数(Least Connections)法
最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它是根据后端服务器当前的连接情况,动态地选取其中当前
积压连接数最少的一台服务器来处理当前的请求,尽可能地提高后端服务的利用效率,将负责合理地分流到每一台服务器。
前面几种方法费尽心思来实现服务消费者请求次数分配的均衡,当然这么做是没错的,可以为后端的多台服务器平均分配工作量,最大程度地提高服务器的利用率,但是实际情况是否真的如此?实际情况中,请求次数的均衡真的能代表负载的均衡吗?这是一个值得思考的问题。
上面的问题,再换一个角度来说就是:以后端服务器的视角来观察系统的负载,而非请求发起方来观察。最小连接数法便属于此类。
最小连接数算法比较灵活和智能,由于后端服务器的配置不尽相同,对于请求的处理有快有慢,它正是根据后端服务器当前的连接情况,动态地选取其中当前积压连接数最少的一台服务器来处理当前请求,尽可能地提高后端服务器的利用效率,将负载合理地分流到每一台机器。由于最小连接数设计服务器连接数的汇总和感知,设计与实现较为繁琐,此处就不说它的实现了。
위 내용은 Java는 여러 로드 밸런싱 알고리즘을 구현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제











Java의 Weka 가이드. 여기에서는 소개, weka java 사용 방법, 플랫폼 유형 및 장점을 예제와 함께 설명합니다.

Java의 Smith Number 가이드. 여기서는 정의, Java에서 스미스 번호를 확인하는 방법에 대해 논의합니다. 코드 구현의 예.

이 기사에서는 가장 많이 묻는 Java Spring 면접 질문과 자세한 답변을 보관했습니다. 그래야 면접에 합격할 수 있습니다.

Java 8은 스트림 API를 소개하여 데이터 컬렉션을 처리하는 강력하고 표현적인 방법을 제공합니다. 그러나 스트림을 사용할 때 일반적인 질문은 다음과 같은 것입니다. 기존 루프는 조기 중단 또는 반환을 허용하지만 스트림의 Foreach 메소드는이 방법을 직접 지원하지 않습니다. 이 기사는 이유를 설명하고 스트림 처리 시스템에서 조기 종료를 구현하기위한 대체 방법을 탐색합니다. 추가 읽기 : Java Stream API 개선 스트림 foreach를 이해하십시오 Foreach 메소드는 스트림의 각 요소에서 하나의 작업을 수행하는 터미널 작동입니다. 디자인 의도입니다

Java의 TimeStamp to Date 안내. 여기서는 소개와 예제와 함께 Java에서 타임스탬프를 날짜로 변환하는 방법에 대해서도 설명합니다.

캡슐은 3 차원 기하학적 그림이며, 양쪽 끝에 실린더와 반구로 구성됩니다. 캡슐의 부피는 실린더의 부피와 양쪽 끝에 반구의 부피를 첨가하여 계산할 수 있습니다. 이 튜토리얼은 다른 방법을 사용하여 Java에서 주어진 캡슐의 부피를 계산하는 방법에 대해 논의합니다. 캡슐 볼륨 공식 캡슐 볼륨에 대한 공식은 다음과 같습니다. 캡슐 부피 = 원통형 볼륨 2 반구 볼륨 안에, R : 반구의 반경. H : 실린더의 높이 (반구 제외). 예 1 입력하다 반경 = 5 단위 높이 = 10 단위 산출 볼륨 = 1570.8 입방 단위 설명하다 공식을 사용하여 볼륨 계산 : 부피 = π × r2 × h (4

Java는 초보자와 숙련된 개발자 모두가 배울 수 있는 인기 있는 프로그래밍 언어입니다. 이 튜토리얼은 기본 개념부터 시작하여 고급 주제를 통해 진행됩니다. Java Development Kit를 설치한 후 간단한 "Hello, World!" 프로그램을 작성하여 프로그래밍을 연습할 수 있습니다. 코드를 이해한 후 명령 프롬프트를 사용하여 프로그램을 컴파일하고 실행하면 "Hello, World!"가 콘솔에 출력됩니다. Java를 배우면 프로그래밍 여정이 시작되고, 숙달이 깊어짐에 따라 더 복잡한 애플리케이션을 만들 수 있습니다.
