Skip to content

Latest commit

 

History

History
130 lines (109 loc) · 4.46 KB

3.Ribbon.md

File metadata and controls

130 lines (109 loc) · 4.46 KB

Ribbon

Client LoadBalancer인 Ribbon을 알아보기 전에 먼저 Server Side LoadBalancer를 간략하게 알아보고 넘어간다.

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 LoadBalancer - Ribbon

  • 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')

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를 통해 생성된다.

Ribbon 장점

  • H/W가 필요없이 S/W만으로 가능 (비용 down, 유연성 up)
  • 서버 목록의 동적 변경이 자유로움 (단, Coding 필요)
  • LB Schema 마음대로 구성 가능 (단, Coding 필요)

Ribbon 적용 샘플

@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 설정을 읽어 치환한다.

Ribbon의 Retry

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)


코드 예제