비트 컴퓨터 [MSA] - ⑨

아현·2022년 5월 4일
0

비트 컴퓨터 교육

목록 보기
3/3

JSONPlaceholder


https://jsonplaceholder.typicode.com/users



https://jsonplaceholder.typicode.com/posts/1

https://jsonplaceholder.typicode.com/posts/1/comments



1. API 사용하기


  • GET /users

  • GET /users/1

  • GET /users/1/comments

  • GET /users?userId=1"



index.jsp


<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
	<h1>App</h1>
	<a href="t1">확인 페이지</a>
	<br/>
	<a href="app/0">0ms 성공</a>
	<br/>
	<a href="app/2000">2000ms 실패</a>
	<br/>
	<a href="users">users</a>
	<br/>
	<a href="users/1">users/1</a>
	<br/>
	<a href="users/1/comments">users/1/comments</a>
	<br/>
	<a href="users?userId=1">users?userId=1</a>
	<br/>
</body>
</html>



Application.java


package Pack01;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.netflix.hystrix.contrib.javanica.annotation.*;

@Controller
public class Application {
	@RequestMapping("/")
	public String f0() {
//		System.out.println("f0 call");
		return "index";
	}
	
	@RequestMapping("/t1")
	public String f1() {
		System.out.println("f1 call");
		return "CheckView";
		//루트로 리다이렉트
//		return "redirect:/";
	}
}


@RestController
@RequestMapping("/app")
class AppController{
	@Bean
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}
	
	@Autowired
	RestTemplate restTemplate;
	
	//성공 - 실패 - 실패 -> 실패 확률(66%) > 50% (50% 이상이면 발생)
	//서킷 발동의 의미: 서비스 호출 자체를 하지 않고, fallbackMethod 함수 호출
	//서킷 발동 8초 이후에 몇 년이 지나서 1회 클릭했을 때
	@GetMapping("/{appNum}") //제품번호가 날라왔다 정도
	@HystrixCommand(
			fallbackMethod = "tiger",
					commandProperties = { 
							@HystrixProperty(
									name = "execution.isolation.thread.timeoutInMilliseconds", 
									value = "500"), //응답을 기다리는 시간
							@HystrixProperty(
									name = "circuitBreaker.errorThresholdPercentage", 
									value = "50"), //50% 이상 문제가 발생하면 서킷을 오픈
							@HystrixProperty(
									name = "metrics.rollingStats.timeInMilliseconds", 
									value = "10000"), //최근 10초 동안
							@HystrixProperty(
									name = "circuitBreaker.requestVolumeThreshold", 
									value = "3"), //최근 10초동안 서비스 호출이 3회 이상이면 통계를 시작하세요 (10초 안에 3번 이상 클릭)
							@HystrixProperty(
									name = "circuitBreaker.sleepWindowInMilliseconds", 
									value = "8000") //서킷브레이크 오픈 유지시간
							}

	)
	public String f1(@PathVariable String appNum) {
		System.out.println();
		String result = restTemplate.getForObject(
				"http://localhost:8082/bpp/" + appNum,
				String.class
		);
		
		return result;
	}
	
	public String tiger(String s) {
		System.out.println(s);
		return "기본 광고";
	}
}



@RestController
@RequestMapping("/users")
class TestController{
//	@GetMapping("")
//	public String f1() {
//		System.out.println("f1");
//		return "f1";
//	}
	
	@GetMapping("/{num}")
	public String f2(@PathVariable String num) {
		System.out.println("f2");
		return "f2 : " + num;
	}
	
	@GetMapping("/{num}/{com}")
	public String f3(@PathVariable String num, 
			@PathVariable String com) {
		System.out.println("f3");
		return "f3 : " + com;
	}
	
	@GetMapping("")
	public String f4(@RequestParam(
			value="usersId", required=false) String usersId) {
		System.out.println("f4");
		return "f4";
	}
}



2. Spring Cloud Ribbon

참고


  • 구성 요소

    • ServerList

      • 로드 밸런싱 대상 서버 목록

      • configuration을 통해 static 하게 설정 가능

      • eureka 등을 기반으로 dynamic하게 설정 가능

    • Rule

      • 요청을 보낼 서버를 선택하는 논리

      • Round Robbin - 한 서버씩 돌아가며 전달

      • Available Filtering - 에러가 많은 서버 제외

      • weighted Response Time - 서버별 응답 시간에 따라 확률 조절

    • Ping

      • 서버 list가 살아있는지 체크하는논리

      • static, dynamic 모두 가능


Ribbon의 가장 중요하다고 생각하는 기능중 하나는 Retry입니다.

  • Retry는 말 그대로 만약 server에게 응답을 받지 못하였을 경우 동일한 서버로 재시도 하거나 다른 서버로 재시도하는 기능입니다.

ribbon의 서버리스트를 환경파일에서 가져올지 eureka에서 동적으로 가져올지 설정할 수도 있습니다.



✅ 로드 밸런싱 (Load Balancing)


  • 기존에는 하드웨어로 지원되던 로드 밸런싱으로 소프트웨어화 시킨 것이 리본

    • 클라우드 측에 심어지는 라이브러리 형태로 존재한다.




  • 하드웨어 기반의 서버 사이드 로드 밸런서의 단점은 기본적으로 별도의 스위치 장비가 필요하기 때문에 상대적으로 비용이 많이 소모되게 되며 유연성도 떨어지게 됩니다.

  • 서버 목록의 추가는 수동으로 보통 이루어집니다.

  • 이러한 단점 때문에 클라이이언트 사이드 로드밸런서가 MSA에서는 주로 사용됩니다.

  • 클라이언트 사이드 로드밸런서를 사용하게 되면 아래와 같이 아키텍처가 형성됩니다.



실습


  1. 의존성 (application.properties)

    • Ribbon을 사용하기 위해서는 먼저 의존성을 부여해야합니다. 아래의 의존성을 부여하면 우리는 Ribbon을 사용할 수 있습니다.

implementation 'org.springframework.cloud:spring-cloud-starter-netflix-ribbon:2.1.4.RELEASE'


# 첫 시도 실패시 같은 서버로 재시도 하는 수(첫번째 전송은 제외)
sample-client.ribbon.MaxAutoRetries=1

# 첫 시도 실패시 다음 서버로 재시도 하는 수(첫번째 전송은 제외)
sample-client.ribbon.MaxAutoRetriesNextServer=1

# Whether all operations can be retried for this client
sample-client.ribbon.OkToRetryOnAllOperations=true

# source로 부터 서버 리스트를 ribbon으로 다시 가져오는 interval time
sample-client.ribbon.ServerListRefreshInterval=2000

# HttpClientConnection timeout(연결과정의 Timeout 시간)
sample-client.ribbon.ConnectTimeout=3000

# HttpClientRead Timeout(데이터를 읽어오는 과정의 Timeout 시간)
sample-client.ribbon.ReadTimeout=3000

# 최초의 서버 리스트, 다이나믹하게 변경될 수 있다.
sample-client.ribbon.listOfServers=www.microsoft.com:80,www.yahoo.com:80,www.google.com:80

sample-client를 생략하게 되면 전체적으로 설정이 걸리게 되며, sample-client에 서비스 이름을 기입하면 해당 서비스에만 적용되어지게 됩니다.



  1. ribbon-Client 생성

    • ribbon을 사용하기 위해서는 ribbon-client를 생성해야합니다.

    • ribbon-client란 로드밸런서 그룹이라고 생각하시면 됩니다. 일반적으로 서비스 단위로 생성하면 됩니다.

@Configuration
@RibbonClients({
        @RibbonClient(name = "service-group-1", configuration = LoadBalancerConfiguration.class)
})
public class RibbonClientConfig {
}
service-group-1.ribbon.MaxAutoRetries=1
service-group-1.ribbon.listOfServers=localhost:8081,localhost:8081



  1. RestTemplate에 Ribbon 적용

    • 클라이언트 사이드 로드밸런싱은 우리가 Http통신에 익히 사용하던 RestTemplate에 적용할 수 있습니다. 아래와 같이 @LoadBalanced를 적용해주시면 쉽게 적용되어 Ribbon의 retry, loadbalancing 등의 특징을 사용할 수 있게 됩니다.

 @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }



4-1. 묵시적 사용


@Service
public class LogisticsServiceImpl {

    RestTemplate restTemplate;

    public LogisticsServiceImpl(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public String getLogisticsInfo() {
        return restTemplate.getForObject("http://server-group-1",String.class);
    }
}



4-2. 명시적 사용


@Service
public class LogisticsServiceImpl {

    @Autowired
    LoadBalancerClient loadBalancerClient;

    RestTemplate restTemplate;

    public LogisticsServiceImpl(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public String getLogisticsInfo() {
        final ServiceInstance choose = loadBalancerClient.choose("server-group-1");
        return restTemplate.getForObject(String.format("http://%s:%s", choose.getHost(), choose.getPort()),String.class);
    }
}



  1. Ribbon customizing

    • Ribbon의 구성요소는 Ping, ServerList, Rule의 3가지라고 했습니다. 이 3가지 요소는 커스터마이징 할 수 있습니다.

    • IPing은 ping관련으로 ribbon-client에 물려있는 서버가 살아있는지 판단할 때 사용합니다. ping이 정상적으로 수행되지 않으면 해당 서버로 실제 요청을 보내지 않습니다. IRule은 로드밸런싱 룰을 설정하는 부분입니다.

    • 이렇게 설정한 것들은 @Configuration으로 주입하면 안되며 @RibbonClient(name = "service-group-1", configuration = LoadBalancerConfiguration.class) 으로 configuration에 들어가도록 적용해주어야 합니다.


public class LoadBalancerConfiguration {

    @Autowired
    IClientConfig ribbonClientConfig;

    @Bean
    public IPing ribbonPing(IClientConfig config) {
        return new PingUrl(false, "/ping");
    }

    @Bean
    public IRule ribbonRule(IClientConfig config) {
        return new AvailabilityFilteringRule();
    }
}



환경 설정



<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-ribbon -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    <version>2.2.10.RELEASE</version>
</dependency>



[Ribbon01] application.yml



server:
  port: 8081

spring:
  mvc: 
    view: 
      prefix: /WEB-INF/views/
      suffix: .jsp

# 내가 tiger라는 주소표기를 사용하면 localhost:8082로 해석하세요
tiger:
  ribbon: 
    listOfServers: localhost:8082 , localhost:8083, localhost:8084 #라운드로빈으로 찾아감
    MaxAutoRetries: 0
    MaxAutoRetriesNextServer: 1



[Ribbon01] Ribbon01Application.java




package Pack01;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class Ribbon01Application {

	@Bean
	@LoadBalanced
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
	
	
	
	public static void main(String[] args) {
		SpringApplication.run(Ribbon01Application.class, args);
	}

}




[Ribbon01] index.jsp



<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
	<h1></h1>
	<a href="t1">확인 페이지</a>
	<br/>
	<a href="app">두번째</a>
	<br/>
</body>
</html>



[Ribbon01] Application.java



package Pack01;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@Controller
public class Application {
	@RequestMapping("/")
	public String f0() {
		System.out.println("f0 call");
		return "index";
	}
	
	@RequestMapping("/t1")
	public String f1() {
		System.out.println("f1 call");
		return "CheckView";
		//루트로 리다이렉트
//		return "redirect:/";
	}
}

@RestController
@RequestMapping("/app")
class AppController{
	@Autowired
	RestTemplate restTemplate;
	
	@GetMapping("")
	public String f1() {
		System.out.println("f1");
		String result = restTemplate.getForObject(
//				"http://localhost:8082/bpp", 
				"http://tiger/bpp", 
				String.class);
		return result;
	}
}



[Ribbon02] application.properties





server.port = 8082
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp



[Ribbon02] Application.java



package Pack01;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@Controller
public class Application {
	@RequestMapping("/")
	public String f0() {
		System.out.println("f0 call");
		return "index";
	}
	
	@RequestMapping("/t1")
	public String f1() {
		System.out.println("f1 call");
		return "CheckView";
		//루트로 리다이렉트
//		return "redirect:/";
	}
}


@RestController
@RequestMapping("/bpp")
class AppController{

	@GetMapping("")
	public String f1() {
		System.out.println("number2");
		return "number2";
	}
}



[Ribbon03] application.properties





server.port = 8083
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp

[Ribbon03] Application.java



package Pack01;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class Application {
	@RequestMapping("/")
	public String f0() {
		System.out.println("f0 call");
		return "index";
	}
	
	@RequestMapping("/t1")
	public String f1() {
		System.out.println("f1 call");
		return "CheckView";
		//루트로 리다이렉트
//		return "redirect:/";
	}
}



@RestController
@RequestMapping("/bpp")
class AppController{
	@GetMapping("")
	public String f1() {
		System.out.println("number3");
		return "number3";
	}
}



[Ribbon04] application.properties





server.port = 8084
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp



[Ribbon04] Application.java



package Pack01;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class Application {
	@RequestMapping("/")
	public String f0() {
		System.out.println("f0 call");
		return "index";
	}
	
	@RequestMapping("/t1")
	public String f1() {
		System.out.println("f1 call");
		return "CheckView";
		//루트로 리다이렉트
//		return "redirect:/";
	}
}



@RestController
@RequestMapping("/bpp")
class AppController{
	@GetMapping("")
	public String f1() {
		System.out.println("number4");
		return "number4";
	}
}



3. Spring Cloud Eureka


http://localhost:8761/



[EurekaServer] application.yml


server:
  port: 8761
eureka:
  instance:
    hostname: localhost
  client:
    registerWithEureka: false
    fetchRegistry: false
    serviceUrl:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/



[EurekaServer] pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>EurekaServer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>EurekaServer</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<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>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.16</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>

		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
			<version>2.2.10.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
			<version>2.2.10.RELEASE</version>
		</dependency>

		<dependency>
		    <groupId>org.springframework.cloud</groupId>
		    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
		    <version>2.2.10.RELEASE</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>



[EurekaServer] EurekaServerApplication.java



package Pack01;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

	@Bean
	RestTemplate restTemplate() {
		return new RestTemplate();
	}
	public static void main(String[] args) {
		SpringApplication.run(EurekaServerApplication.class, args);
	}

}



[EurekaServer] Application.java



package Pack01;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@Controller
public class Application {
	@RequestMapping("/")
	public String f0() {
		System.out.println("f0 call");
		return "index";
	}
	
	@RequestMapping("/t1")
	public String f1() {
		System.out.println("f1 call");
		return "CheckView";
		//루트로 리다이렉트
//		return "redirect:/";
	}
}



[EurekaClient01] application.yml



server:
  port: 8081

spring:
  mvc: 
    view: 
      prefix: /WEB-INF/views/
      suffix: .jsp
  application:
    name: Service01
    
eureka:
  instance:
    prefer-ip-address: true
    



[EurekaClient01] pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>EurekaClient01</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>EurekaClient01</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<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>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.16</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>

		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-amqp</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
			<version>2.2.10.RELEASE</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>



[EurekaClient01] EurekaClient01Application.java


package Pack01;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableEurekaClient
@SpringBootApplication
public class EurekaClient01Application {
   @Bean
   @LoadBalanced
   RestTemplate restTemplate() {   
	   return new RestTemplate(); 
   }
   
   public static void main(String[] args) {
      SpringApplication.run(EurekaClient01Application.class, args);
   }
}



[EurekaClient01] Application.java


package Pack01;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@Controller
public class Application {
	@RequestMapping("/")
	public String f0() {
		System.out.println("f0 call");
		return "index";
	}
	
	@RequestMapping("/t1")
	public String f1() {
		System.out.println("f1 call");
		return "CheckView";
		//루트로 리다이렉트
//		return "redirect:/";
	}
}


@RestController
@RequestMapping("/app")
class AppController{	

	@Autowired
	RestTemplate restTemplate;
	
	@GetMapping("")
	public String f1() {
		//System.out.println(restTemplate);
		
		String result = restTemplate.getForObject( 
			"http://Service02/bpp",
			String.class);
		
		return "test : " + result;
	}
}



[EurekaClient02] application.yml



server:
  port: 8082

spring:
  mvc: 
    view: 
      prefix: /WEB-INF/views/
      suffix: .jsp
  application:
    name: Service02
    
eureka:
  instance:
    prefer-ip-address: true
    



[EurekaClient02] pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>EurekaClient02</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>EurekaClient02</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<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>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.16</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>

		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
			<version>2.2.10.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-amqp</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
			<version>2.2.10.RELEASE</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>



[EurekaClient02] EurekaClient02Application.java


package Pack01;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableEurekaClient
@SpringBootApplication
public class EurekaClient02Application {
//	@Bean
//	@LoadBalanced
//	RestTemplate restTemplate() {   
//		return new RestTemplate(); 
//	}

	public static void main(String[] args) {
		SpringApplication.run(EurekaClient02Application.class, args);
	}

}



[EurekaClient02] Application.java


package Pack01;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class Application {
	@RequestMapping("/")
	public String f0() {
		System.out.println("f0 call");
		return "index";
	}
	
	@RequestMapping("/t1")
	public String f1() {
		System.out.println("f1 call");
		return "CheckView";
		//루트로 리다이렉트
//		return "redirect:/";
	}
}


@RestController
@RequestMapping("/bpp")
class AppController{	
	@GetMapping("")
	public String f1() {
		System.out.println("test1");
		return "test : 1";
	}
}



[EurekaClient03] application.yml


server:
  port: 8083

spring:
  mvc: 
    view: 
      prefix: /WEB-INF/views/
      suffix: .jsp
  application:
    name: Service02
    
eureka:
  instance:
    prefer-ip-address: true
    



[EurekaClient03] pom.xml


<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>EurekaClient03</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>EurekaClient03</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<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>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.16</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>

		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
			<version>2.2.10.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-amqp</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
			<version>2.2.10.RELEASE</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>


</project>



[EurekaClient03] EurekaClient03Application.java



package Pack01;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableEurekaClient
@SpringBootApplication
public class EurekaClient03Application {
//	@Bean
//	@LoadBalanced
//	RestTemplate restTemplate() {   
//		return new RestTemplate(); 
//	}

	public static void main(String[] args) {
		SpringApplication.run(EurekaClient03Application.class, args);
	}

}



[EurekaClient03] Application.java


package Pack01;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Controller
public class Application {
	@RequestMapping("/")
	public String f0() {
		System.out.println("f0 call");
		return "index";
	}
	
	@RequestMapping("/t1")
	public String f1() {
		System.out.println("f1 call");
		return "CheckView";
		//루트로 리다이렉트
//		return "redirect:/";
	}
}


@RestController
@RequestMapping("/bpp")
class AppController{	
	@GetMapping("")
	public String f1() {
		System.out.println("test1");
		return "test : 1";
	}
}




profile
Studying Computer Science

0개의 댓글