본문 바로가기
푸닥거리

Spring Cloud를 활용한 MSA 설치 및 구성-2

by [김경민]™ ┌(  ̄∇ ̄)┘™ 2022. 7. 24.
728x90
spring.application.name=Service04
server.port=8084

 

Spring Cloud를 활용한 MSA 설치 및 구성-2

 

 

 

마이크로서비스 기반 아키텍처(MSA) VS 서비스 지향 아키텍처(SOA)

 

* Microservices3Monitoring 도구
• Hystrix 대시보드
• 유레카(Eureka) 관리자 대시보드
• 스프링 부트 관리자 대시보드

 

server:
  port: 9000

spring:
  cloud:
    gateway:
      routes:
      - id: helloModule
        uri: http://localhost:8086/
        predicates:
        - Path=/hello/**
      - id: goodbyeModule
        uri: http://localhost:8087/
        predicates:
        - Path=/goodbye/**

 

 

 

http://localhost:9000/hello
-> http://localhost:8086/hello

http://localhost:9000/goodbye
-> http://localhost:8087/goodbye

Gateway Server http://localhost:9000/hello or goodbye

Service #1 http://localhost:8086
Service #1 http://localhost:8087


ApiGateway 9001 - gateway, eurekaclient 
Loadbalancer 9000 - loadbalancer, eurekaclient
EurekaServer 8090 - eurekaserver
Service01 8081 - eurekaclient, spring mvc
Service02 8082 - eurekaclient, spring mvc

 

 

 

package com.test.model;

public class Member {
private String id;
private String name;
}

 

package com.test.model;

public class Member {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
}

 

 

 

 

 

package com.test.controllers;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.test.model.Member;

@RestController
public class MemberController {
	@RequestMapping(value="/member", method=RequestMethod.GET)
	public Member getInfo() {
		Member m = new Member();
		m.setId("hong");
		m.setName("홍길동");
		return m;
	}
}

 

 

<?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.7.2</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.test</groupId>
	<artifactId>Service01</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>Service01</name>
	<description>Demo project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
		<spring-cloud.version>2021.0.3</spring-cloud.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<!-- 
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-config</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
		</dependency>
		 -->
		 
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>

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

</project>

 

 

 

spring.application.name=EurekaServer
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
server.port=8090

 

 

 

package com.test;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {

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

}

spring.application.name=Service01
server.port=8081
eureka.client.service-url.defaultZone=http://localhost:8090/eureka

 

 

 

spring.application.name=EurekaServer
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
server.port=8090
eureka.client.service-url.defaultZone=http://localhost:8090/eureka/


http://localhost:8080/member1
http://localhost:8080/member2
http://localhost:8090
http://localhost:8081/member
http://localhost:8082/member2

 

 

 

 

package com.test.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.stereotype.Controller;

@Controller
public class ConsumerControllerClient {
	@Autowired
	private LoadBalancerClient loadBalancer;
	public void getHello() {
		ServiceInstance serviceInstance = loadBalancer.choose("SERVICE");
		System.out.println(serviceInstance.getUri());
		String baseUrl = serviceInstance.getUri().toString();
		baseUrl = baseUrl = "/member";
		// http://localhost:9000/member
		// -> http://localhost:8081/member -> SERVICE01
		// -> http://loaclhost:8082/member -> SERVICE02
	}
}

package com.test.controllers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.client.RestTemplate;

@Controller
public class ConsumerControllerClient {
	@Autowired
	private LoadBalancerClient loadBalancer;
	public void getHello() {
		ServiceInstance serviceInstance = loadBalancer.choose("SERVICE");
		System.out.println(serviceInstance.getUri());
		String baseUrl = serviceInstance.getUri().toString();
		baseUrl = baseUrl = "/member";
		// http://localhost:9000/member
		// -> http://localhost:8081/member -> SERVICE01
		// -> http://loaclhost:8082/member -> SERVICE02
		RestTemplate restTemplate = new RestTemplate();
	}
}
package com.test.controllers;

import java.io.IOException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.client.RestTemplate;

@Controller
public class ConsumerControllerClient {
	@Autowired
	private LoadBalancerClient loadBalancer;
	public void getMember() {
		ServiceInstance serviceInstance = loadBalancer.choose("SERVICE");
		System.out.println(serviceInstance.getUri());
		String baseUrl = serviceInstance.getUri().toString();
		baseUrl = baseUrl = "/member";
		// http://localhost:9000/member
		// -> http://localhost:8081/member -> SERVICE01
		// -> http://loaclhost:8082/member -> SERVICE02
		RestTemplate restTemplate = new RestTemplate(); 

		ResponseEntity<String> response=null;
		try{
			response=restTemplate.exchange(baseUrl,  HttpMethod.GET, getHeaders(),String.class);
		} catch (Exception ex) {
			System.out.println(ex);
		}
		System.out.println(response.getBody());
	}

	private static HttpEntity<?> getHeaders() throws IOException {
		HttpHeaders headers = new HttpHeaders();
		headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
		return new HttpEntity<>(headers);
	}
}
package com.test;

import java.io.IOException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.ApplicationContext;
import org.springframework.web.client.RestClientException;

import com.test.controllers.ConsumerControllerClient;

@SpringBootApplication
public class LoadbalancerApplication {

	public static void main(String[] args) throws RestClientException, IOException {

		ApplicationContext ctx = SpringApplication.run(LoadbalancerApplication.class, args);
		
		ConsumerControllerClient consumerControllerClient=ctx.getBean(ConsumerControllerClient.class);
		System.out.println(consumerControllerClient);
		for(int inx = 0; inx <= 10; inx++) {
			consumerControllerClient.getMember();
		}
	}

}

 

 

 

 

 

 

Service
/member

 

spring.application.name=LoadBalancer1
server.port=9000
eureka.client.serviceUrl.defaultZone=http://localhost:8090/eureka
package com.test.controllers;

import java.io.IOException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.client.RestTemplate;

@Controller
public class ConsumerControllerClient {
	@Autowired
	private LoadBalancerClient loadBalancer;
	public void getMember() {
		ServiceInstance serviceInstance = loadBalancer.choose("SERVICE");
		System.out.println(serviceInstance.getUri());
		String baseUrl = serviceInstance.getUri().toString();
		baseUrl = baseUrl = "/member";
		// http://localhost:9000/member
		// -> http://localhost:8081/member -> SERVICE01
		// -> http://loaclhost:8082/member -> SERVICE02
		RestTemplate restTemplate = new RestTemplate(); 

		ResponseEntity<String> response=null;
		try{
			response=restTemplate.exchange(baseUrl,  HttpMethod.GET, getHeaders(),String.class);
		} catch (Exception ex) {
			System.out.println(ex);
		}
		System.out.println(response.getBody());
	}

	private static HttpEntity<?> getHeaders() throws IOException {
		HttpHeaders headers = new HttpHeaders();
		headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
		return new HttpEntity<>(headers);
	}
}
package com.test;

import java.io.IOException;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.ApplicationContext;
import org.springframework.web.client.RestClientException;

import com.test.controllers.ConsumerControllerClient;

@SpringBootApplication
public class LoadbalancerApplication {

	public static void main(String[] args) throws RestClientException, IOException {

		ApplicationContext ctx = SpringApplication.run(LoadbalancerApplication.class, args);
		
		ConsumerControllerClient consumerControllerClient=ctx.getBean(ConsumerControllerClient.class);
		System.out.println(consumerControllerClient);
		for(int inx = 0; inx <= 10; inx++) {
			consumerControllerClient.getMember();
		}
	}

}

//EurekaServer 미사용 코드 쿠현
package com.test;

import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

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

@SpringBootApplication
public class LoadBalancerClientApplication {

	public static void main(String[] args) {
//		SpringApplication.run(LoadBalancerClientApplication.class, args);
		
		ConfigurableApplicationContext ctx = new SpringApplicationBuilder(LoadBalancerClientApplication.class)
                .web(WebApplicationType.NONE)
                .run(args);

        WebClient loadBalancedClient = ctx.getBean(WebClient.Builder.class).build();

        for(int i = 1; i <= 10; i++) {
            String response =
                loadBalancedClient.get().uri("http://example-service/hello")
                    .retrieve().toEntity(String.class)
                    .block().getBody();
            System.out.println(response);
        }
    }
}
@Configuration
class DemoServerInstanceConfiguration {
    @Bean
    ServiceInstanceListSupplier serviceInstanceListSupplier() {
        return new DemoInstanceSupplier("example-service");
    }
}

@Configuration
@LoadBalancerClient(name = "example-service", configuration = DemoServerInstanceConfiguration.class)
class WebClientConfig {
    @LoadBalanced
    @Bean
    WebClient.Builder webClientBuilder() {
        return WebClient.builder();
    }
}

class DemoInstanceSupplier implements ServiceInstanceListSupplier {
    private final String serviceId;

    public DemoInstanceSupplier(String serviceId) {
        this.serviceId = serviceId;
    }

    @Override
    public String getServiceId() {
        return serviceId;
    }

    @Override
    public Flux<List<ServiceInstance>> get() {
        return Flux.just(Arrays
            .asList(new DefaultServiceInstance(serviceId + "1", serviceId, "localhost", 8082, false),
                    new DefaultServiceInstance(serviceId + "2", serviceId, "localhost", 8083, false)));
    }
}

 

EurekaServer and Ribbon

 

 

 

 

spring.application.name=Service04
server.port=8084
package com.test.controllers;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.test.model.Member;

@RestController
public class MemberController {
	@RequestMapping(value="/goodbye", method=RequestMethod.GET)
	public Member getInfo() {
		Member m = new Member();
		m.setId("lee");
		m.setName("이순신");
		return m;
	}
}

 

 

 

server:
  port: 9000

spring:
  cloud:
    gateway:
      routes:
      - id: helloModule
        uri: http://localhost:8083/
        predicates:
        - Path=/hello/**
      - id: goodbye
        uri: http://localhost:8084/
        predicates:
        - Path=/goodbye/**

 

 

 

spring cloud config server github

spring:
  cloud:
    config:
      server:
        git:
          uri: https://github.com/spring-cloud-samples/config-repo

https://github.com/spring-cloud/spring-cloud-config

 

GitHub - spring-cloud/spring-cloud-config: External configuration (server and client) for Spring Cloud

External configuration (server and client) for Spring Cloud - GitHub - spring-cloud/spring-cloud-config: External configuration (server and client) for Spring Cloud

github.com

 

 

server:
 port: 8888
spring:
 cloud:
  config:
   server:
    git:
     uri: https://github.com/formin/MySpringClud.git

 

server:
 port: 8089
spring:
 application:
  name: MyConfigClient
 cloud:
  config:
   name: myconfig
   profile: test
 config:
  import:
   configserver:http://localhost:8888

package com.test;

import org.springframework.beans.factory.annotation.Value;
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;

@SpringBootApplication
@RestController
public class MyConfigClient1Application {

	public static void main(String[] args) {
		SpringApplication.run(MyConfigClient1Application.class, args);
	}
	
	@Value("${message.text:default}")
	private String messageValue;
	
	@RequestMapping(value="/")
	public String getMessageValue() {
		return messageValue;
	}
}

java -jar jenkins.war

 

 

 

 

 

https://www.amazon.com/-/ko/dp/1617294543/ref=sr_1_4?crid=L81WLGU5KNN3&keywords=microservices&qid=1658649531&sprefix=microservices%2Caps%2C244&sr=8-4 

 

Amazon.com

Enter the characters you see below Sorry, we just need to make sure you're not a robot. For best results, please make sure your browser is accepting cookies.

www.amazon.com

 

 

 

https://www.amazon.com/-/ko/dp/1680506455/ref=sr_1_12?crid=L81WLGU5KNN3&keywords=microservices&qid=1658649573&sprefix=microservices%2Caps%2C244&sr=8-12 

 

Amazon.com

Enter the characters you see below Sorry, we just need to make sure you're not a robot. For best results, please make sure your browser is accepting cookies.

www.amazon.com

 

https://www.amazon.com/-/ko/dp/1801072973/ref=sr_1_1?crid=2KVRM4K5KHJSA&keywords=spring+cloud+microservice&qid=1658649630&sprefix=spring+cloud+microservic%2Caps%2C229&sr=8-1 

 

Amazon.com

Enter the characters you see below Sorry, we just need to make sure you're not a robot. For best results, please make sure your browser is accepting cookies.

www.amazon.com

 

https://www.amazon.com/-/ko/dp/1789613477/ref=sr_1_2?crid=2KVRM4K5KHJSA&keywords=spring+cloud+microservice&qid=1658649671&sprefix=spring+cloud+microservic%2Caps%2C229&sr=8-2 

 

Amazon.com

Enter the characters you see below Sorry, we just need to make sure you're not a robot. For best results, please make sure your browser is accepting cookies.

www.amazon.com

 

https://www.amazon.com/s?k=microservices&crid=L81WLGU5KNN3&sprefix=microservices%2Caps%2C244&ref=nb_sb_noss_1 

 

 

https://www.amazon.com/s?k=microservices&crid=L81WLGU5KNN3&sprefix=microservices%2Caps%2C244&ref=nb_sb_noss_1 

 

 

https://www.amazon.com/-/ko/dp/1449374646/ref=sr_1_10?crid=1G3KQESD8AX8I&keywords=cloud+native&qid=1658649736&sprefix=cloud+nativ%2Caps%2C231&sr=8-10 

 

Amazon.com

Enter the characters you see below Sorry, we just need to make sure you're not a robot. For best results, please make sure your browser is accepting cookies.

www.amazon.com

 

 

 

728x90

댓글