Ribbon이란?

  • 클라이언트 사이드 load balancer
  • 로드밸런싱 룰을 커스터마이징 가능

@LoadBalanced

RestTemplate, WebClient가 Bean으로 선언된 것에 한해서 @LoadBalanced 어노테이션을 붙이면 Intercept를 통해서 LoadBalancer를 끼어넣게된다. 따라서 알아서 로드 밸런싱을 하게된다.

이 때, RestTemplate, WebClient에 주는 주소는 IP, Port를 지우고 호출할 서버 군의 이름을 적으면 군에 해당하는 목록을 알아서 LoadBalancer에서 호출한다.

 

서버쪽 설정

서버에 들어올 경우 어디로 들어왔는지 콘솔에 로그를 남기도록 간단하게 구현했다.

pom.xml

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
package com.example.circuitbreakerbookstore;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.List;
import java.util.Random;

@RestController
@SpringBootApplication
public class CircuitBreakerBookstoreApplication {
    private static Logger logger = LoggerFactory.getLogger(CircuitBreakerBookstoreApplication.class);

    @RequestMapping(value = "/recommended")
    public String readingList(){
        logger.info("Access /recommended");
        Random random = new Random();
        List<String> bookList = Arrays.asList("Spring in ACtion (Manning)", "Cloud Native Java", "Learning Spring Boot");
        int randomNum = random.nextInt(bookList.size());
        return bookList.get(randomNum);
    }

    @RequestMapping(value = "/")
    public String home(){
        logger.info("Access home");
        return "Welcome home";
    }
    public static void main(String[] args){
        SpringApplication.run(CircuitBreakerBookstoreApplication.class, args);
    }
}

 

클라이언트 쪽 설정

pom.xml

 <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
@EnableCircuitBreaker
@RestController
@SpringBootApplication
//다른 자바 설정파일 처럼 @Configuration을 사용하면 안된다. @ComponentScan으로 해당 설정이 로딩될 경우 에러갈 발생한다.
@RibbonClient(name="say-book", configuration = SayBookConfiguration.class) //RibbonClient Annotaion은 Controller에 넣어야한다.
public class CircuitBreakerReadingApplication {

    @Autowired
    private BookService bookService;

    @Bean
    @LoadBalanced
    public WebClient.Builder WebClient(){ //공홈에서는 RestTemplate를 썻지만 그냥 Webflux를 써봤다.
        return WebClient.builder();
    }

    @RequestMapping("/to-read")
    public String toRead(@RequestParam(value="name", defaultValue = "Aroon") String name)
    {

        return String.format("%s, %s",name,bookService.readingList());
    }

    public static void main(String[] args) {
        SpringApplication.run(CircuitBreakerReadingApplication.class, args);
    }
}
public class SayBookConfiguration {
    @Autowired
    IClientConfig ribbonClientConfig;

    @Bean // 첫번째 Parameter가 True일 경우 https false일 경우 http. AppendString은 Ping 보낼 URL
    public IPing ribbonPing(IClientConfig config){
        return new PingUrl(false, "/");
    }

    @Bean //LoadBalancing Rule을 설정하는 것
    public IRule ribbonRule(IClientConfig config){
        return new AvailabilityFilteringRule();
    }
}
@Service
public class BookService {
    @Autowired
    WebClient.Builder webClientBuilder;
    /*
        Hystrix Command 설정
        commandKey 별로 Circuit Breaker 생성
        fallbackMethod : 실패시 해당 메소드 실행
     */
    @HystrixCommand(commandKey = "EX", fallbackMethod = "reliable")
    public String readingList(){
        return webClientBuilder.baseUrl("http://say-book").build().get() //get 방식
                .uri("recommended") //endpoint
                .retrieve() // body를 가지고 온다는 뜻
                .bodyToMono(String.class)
                .block()
                ;
    }

    public String reliable(){
        return "Success Fallback";
    }
}

Eureka와 연동하지 않을 것이므로 false를 하고 Server 군의 목록을 지정해준다.

ServerListRefreshInterval마다 IPing이 실행되며 서버 상태를 확인한다.

server.port= 8888
say-book.ribbon.eureka.enabled=false #유레카를 사용하지 않겠다. 
say-book.ribbon.listOfServers=localhost:8090,localhost:9092 #서버군 목록
say-book.ribbon.ServerListRefreshInterval= 15000 #서버리스트 refresh 간격 ms

 

실행방법 :

 

1. 서버를 아래 mvn 명령어도 두개를 실행한다.

SERVER_PORT=9092 mvn spring-boot:run

SERVER_PORT=8090 mvn spring-boot:run

 

*만약 Maven이 설치되어 있지 않은 경우 homebrew insall maven 명령어로 설치해준다.

 

2. Client를 실행 후 접속해서 확인해본다.

 

 

 

참고 

https://gunju-ko.github.io/spring-cloud/netflixoss/2018/12/14/Ribbon.html

 

Ribbon

Ribbon Netflix가 만든 Software Load Balancer를 내장한 REST Library이다. Ribbon은 Client 사이드 LoadBalancer로 Ribbon을 사용하면 L4등과 같이 하드웨어에서 이루어지던 Load Balance를 애플리케이션 영역에서 할 수 있다. Ribbon을 사용하면 애플리케이션 영역에서 서버목록을 가지고 번갈아가면서 호출하게 된다. Spring Cloud에서 Ribbon 클라이언트를 직접 사용하는 경우는

gunju-ko.github.io

https://spring.io/guides/gs/client-side-load-balancing/

 

Spring

Level up your Java code and explore what Spring can do for you.

spring.io

https://piotrminkowski.com/2018/05/04/reactive-microservices-with-spring-webflux-and-spring-cloud/

 

Reactive Microservices with Spring WebFlux and Spring Cloud

I have already described Spring reactive support about one year ago in the article Reactive microservices with Spring 5. At that time project Spring WebFlux has been under active development, and n…

piotrminkowski.com

 

'Spring' 카테고리의 다른 글

SpringBoot Hystrix 적용하기  (0) 2020.03.01
Hystrix 란  (0) 2020.03.01

+ Recent posts