Client LoadBalancer인 Ribbon을 알아보기 전에 먼저 Server Side LoadBalancer를 간략하게 알아보고 넘어간다.
- 일반적인 L4 Switch 기반의 LoadBalancing
- Client는 L4의 주소만 알고 있고, L4 Switch는 Server 목록을 알고 있다.
- H/W Server Side LoadBalancer의 단점
- H/W가 필요 (비용 up, 유연성 down)
- 서버 목록의 추가를 위해 설정 필요 (자동화가 어렵다)
- LoadBalancing Schema 한정적 (Round Robbin, Sticky)
- 12 factors의 dev/prod를 만족하기 어렵다
- Client에 탑재되는 S/W 모듈
- 주어진 서버 목록에 대해서 LB를 수행함
- Netflix가 만든 Software Load Balancer를 내장한 라이브러리
- spring cloud에서 ribbon 클라이언트를 직접 사용하지 않고, 대부분 설정을 통해 사용하게 된다. 왜냐하면 이후 보게될 spring-cloud-zuul, spring-cloud-openfeign에는 ribbon이 내장되어 옵션 설정만으로 ribbon을 사용할 수 있도록 되어 있다.
compile('org.springframework.cloud:spring-cloud-starter-netflix-ribbon')
- rule 기반의 LB를 제공한다. 라운드 로빈, 응답 가중치 방식 등 기본적인
IRule
인터페이스 구현체를 제공한다. 만약 rule을 커스터마이징하고 싶다면 IRule 인터페이스를 구현하면 된다.
public interface IRule{
Server choose(Object key);
void setLoadBalancer(ILoadBalancer lb);
ILoadBalancer getLoadBalancer();
}
- Service Discovery로부터 서버 목록을 동적으로 가져올 수 있다. 이후 보게될 Eureka Server로부터 서버 목록을 가져오는
DiscoveryEnabledNIWSServerList
구현체가 제공된다.
public interface ServerList<T extends Server> {
List<T> getInitialListOfServers();
/**
* Return updated list of servers. This is called say every 30 secs
* (configurable) by the Loadbalancer's Ping cycle
*
*/
List<T> getUpdatedListOfServers();
}
- IPing을 통해 각 서버가 살아있는지 검사하고, 더이상 살아있지 않은 서버는 LB 목록에서 제외한다.
public interface IPing {
boolean isAlive(Server server);
}
- Archaius라는 것을 사용해 LB와 Client를 설정 기반으로 생성하는 기능을 제공한다. LB와 Client는 ClientFactory를 통해 생성된다.
- H/W가 필요없이 S/W만으로 가능 (비용 down, 유연성 up)
- 서버 목록의 동적 변경이 자유로움 (단, Coding 필요)
- LB Schema 마음대로 구성 가능 (단, Coding 필요)
@EnableCircuitBreaker
@SpringBootApplication
public class HomeApplication {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(HomeApplication.class, args);
}
}
@HystrixCommand(commandKey = "AnyExternal", fallbackMethod = "anyFallback")
public String anyMethodWithExternal() {
String url = "http://external";
URI uri = URI.create(url + "/any");
return restTemplate.getForObject(uri,String.class);
}
public String anyFallback() {
return "No available";
}
# HomeApplication의 yml
external:
ribbon:
listOfServers: localhost:8081
- Ribbon의 기본 LB 정책은 RR
@LoadBalanced
이 RestTemplate에 interceptor를 추가하고, url의 external을 yml 설정을 읽어 치환한다.
compile('org.springframework.retry:spring-retry')
# HomeApplication의 yml
external:
ribbon:
listOfServers: localhost:8081, localhost:9999
MaxAutoRetries: 0
MaxAutoRetriesNextServer: 1
- localhost:9999는 없는 주소이므로 Exception이 발생하지만, Ribbon Retry로 항상 성공한다.
주의
- Retry를 시도하다가도 Hystrix Timeout이 발생하면, Hystrix로 Ribbon을 감싸서 호출했기 때문에 즉시 에러를 리턴한다.
- Retry를 끄거나 재시도 횟수를 0으로 해도 해당 서버로의 호출이 항상 동일한 비율로 실패하진 않는다.
실패한 서버로의 호출은 특정 시간동안 skip되고 그 간격은 조정된다. - BackOff)