spring cloud vs kubernetes
-> jdk-11.0.15.1_windows-x64_bin.exe
-> spring-tool-suite-4-4.15.1.RELEASE-e4.24.0-win32.win32.x86_64.self-extracting.jar
-> apache-maven-3.8.6-bin.zip
jdk 11 설치
maven 압축해제
JAVA_HOME C:\Program Files\Java\jdk-11.0.15.1
Path %JAVA_HOME%\bin
MAVEN_HOME C:\apache-maven-3.8.6
Path %MAVEN_HOME%\bin
명령창 테스트
java -version
javac -version
mvn
캐시경로
C:\Users\HPE.m2\repository
https://projectlombok.org/download
java -jar lombok.jar을 STS에 설치
http://localhost:8080/v1/organization/optimaGrowth/license/2313202
eureka server
spring.application.name=MyServer
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
server.port=8761
spring.application.name=MyClient1
server.port=8081
eureka.instance.prefer-ip-address=true
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.client.fetch-registry=true
eureka.client.register-with-eureka=true
package com.test.myclient1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication
@EnableEurekaClient
@RestController
public class MyClient1Application {
public static void main(String[] args) {
SpringApplication.run(MyClient1Application.class, args);
}
@RequestMapping(value="/")
public String hello() {
return "Eureka Client Application";
}
}
spring.application.name=MyClient2
server.port=8082
eureka.instance.prefer-ip-address=true
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.client.fetch-registry=true
eureka.client.register-with-eureka=true
spring.application.name=MyClient3
server.port=8083
eureka.instance.prefer-ip-address=true
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.client.fetch-registry=true
eureka.client.register-with-eureka=true
package com.test.myclient3;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.test.myclient3.MyClient3Application;
@SpringBootApplication
@EnableEurekaClient
@RestController
public class MyClient3Application {
public static void main(String[] args) {
SpringApplication.run(MyClient3Application.class, args);
}
@RequestMapping(value="/")
public String hello() {
return "Eureka Client Application #3";
}
}
마이크로서비스 기반 아키텍처(MSA) VS 서비스 지향 아키텍처(SOA)
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;
}
}
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
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
Microservice Patterns: With examples in Java
Practical Microservices: Event Sourcing and CQRS with Event-Driven Architectures
스프링 부트 및 스프링 클라우드가 있는 핸드온 마이크로서비스: 스프링 클라우드, 이스티오, 쿠버네티스를 사용하여 Java 마이크로서비스 구축 및 배포
Cloud Native Java: 스프링 부츠, 스프링 클라우드 및 클라우드 파운드리가 있는 탄력적인 시스템 설계