깃 : https://github.com/kdh11112/brilliant-growth/tree/main/springbootex19_springcloud
@SpringBootApplication
@EnableEurekaServer //유레카 서버 활성화
public class Springbootex14DiscoveryApplication {
public static void main(String[] args) {
SpringApplication.run(Springbootex14DiscoveryApplication.class, args);
}
}
유레카 서버를 활성화 하는 코드 이다
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
폼에 유레카 서버에 관한 정보를 줘야한다
server:
port: 8761
spring:
application:
name: discoveryservice
eureka:
client:
register-with-eureka: false #eureka 서버에 등록할지 여부를 설정 (내가 서버가 될거라 등록이 안됨)
fetch-registry: false #eureka 서버로 부터 정보를 가져올지를 선택
포트는 8761을 사용하는데 관습적인 이유이다
zuul을 을 사용한 게이트웨이
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
@SpringBootApplication
@EnableZuulProxy
public class Springbootex18ZuulserviceApplication {
public static void main(String[] args) {
SpringApplication.run(Springbootex18ZuulserviceApplication.class, args);
}
}
zuul을 사용하기 위해서 @EnableZuulProxy를 사용해야한다
server:
port: 8000
spring:
application:
name: my-zuul-service
zuul:
routes:
first-service:
path: /first-service/**
url: http://localhost:8081
second-service:
path: /second-service/**
url: http://localhost:8082
yml에 게이트웨이에 등록할 서버를 설정해준다
현재 여기선 로컬로 2개를 만들어줬다
@Slf4j
@Component
public class zuulLogginFilter extends ZuulFilter{
@Override
public boolean shouldFilter() {
return true; //필터 사용
}
@Override
public Object run() throws ZuulException {
//필터가 동작 된다면 이부분이 실행됨
log.info("로그 시작 ===============>");
//요청 URI 를 로그로 기록
//1번방식
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String uri = request.getRequestURI();
log.info("요청 uri : {}",uri);
//2번방식 ==> 1번과 똑같은 거임
log.info("요청 uri : {}",RequestContext.getCurrentContext().getRequest().getRequestURI());
log.info("로그 끝 ===============>");
return null;
}
@Override
public String filterType() {
// TODO Auto-generated method stub
return "pre"; //진입 쪽 필터
}
@Override
public int filterOrder() {
// TODO Auto-generated method stub
return 0;
}
}
zuul 필터를 사용하는 간단한 방법
spring cloud gateway에 대해 알아보자
현재 스프링에서는 zuul대신 scg를 권고하고 있다
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
1번째껀 scg를 사용하기 위해 쓰고
2번째껀 유레카 서버에 클라이언트 등록을 위해 사용해야한다
scg 는 Application에 어노테이션을 따로 지정하지 않아도 된다.
server:
port: 8000
spring:
application:
name: apigateway-service
cloud:
gateway:
default-filters:
- name: GlobalFilter
args:
baseMessage: Hello Spring Cloud Global Filter
preLogger: true
postLogger: true
routes:
- id: first-service
predicates:
- Path=/first-service/**
uri:
lb://MY-FIRST-SERVICE
# http://localhost:8081 로드밸런싱을 위하여 포트번호를 지정하면 안됨
filters:
- CustomFilter
# - AddRequestHeader=first-request, first-request-header-from-yml
# - AddResponseHeader=first-response, first-response-header-from-yml
- id: second-service
predicates:
- Path=/second-service/**
uri:
lb://MY-SECOND-SERVICE
# http://localhost:8082
filters:
- CustomFilter
# - AddRequestHeader=second-request, second-request-header-from-yml
# - AddResponseHeader=second-response, second-response-header-from-yml
# 여기가다 설정해도 되고 FilterConfig에다가 설정해도 됨
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka
yml에 설정한 내용은 2개의 서버를 지정하였고 로드밸런싱을 위하여 포트번호는 랜덤으로 부여
필터는 커스텀 필터를 사용하였다는 뜻이다
서버는 유레카 서버로 지정
필터는 야믈에ㅁ
# - AddRequestHeader=second-request, second-request-header-from-yml
# - AddResponseHeader=second-response, second-response-header-from-yml
이런식으로 지정해도 되지만 Config파일을 따로 만들어서 설정해줘도된다
// 빈 정의할때 스는 어노테이션
@Configuration
public class FilterConfig {
@Bean
public RouteLocator gatewayRoutes(RouteLocatorBuilder builder) {
//여기다가 설정을 하게되면 야뮬 파일에서 설정을 한거랑 같은거임
return builder .routes()
.route(r -> r.path("/first-service/**")
.filters(f -> f.addRequestHeader("first-service", "first-request-header")
.addResponseHeader("first-service", "first-response-header")
)
.uri("http://localhost:8081")
)
.route(r -> r.path("/second-service/**")
.filters(f -> f.addRequestHeader("second-service", "second-request-header")
.addResponseHeader("second-service", "second-response-header")
)
.uri("http://localhost:8082")
)
.build();
}
아래는 커스텀필터이다
@Slf4j
//커스텀 필터
@Component
public class CustomFilter extends AbstractGatewayFilterFactory<CustomFilter.Config>{
//설정 정보를 제공하는 클래스
public static class Config{
}
public CustomFilter() {
super(Config.class);
}
//필터의 동작을 정의한 메소드
@Override
public GatewayFilter apply(Config config) {
// GatewayFilter gf = new GatewayFilter() {//인터페이스 이기에 이너 클래스로 바로 만듬
//
// @Override
// public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// ServerHttpRequest request = exchange.getRequest();
// ServerHttpResponse response = exchange.getResponse();
//
// log.info("Customer pre Filter : request id = {}",request.getId());
// Mono<Void> m = chain.filter(exchange).then(Mono.fromRunnable(() ->{
// log.info("Custom POST filter : response code = {}",response.getStatusCode());
// }));
//
// return m;
// }
// };
//
// return gf;
//위의 코드를 람다식으로 정의 하는방법
return (exchange,chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Customer pre Filter : request id {}",request.getId());
return chain.filter(exchange).then(Mono.fromRunnable(() ->{
log.info("Customer POST filter : response code = {}",response.getStatusCode());
}));
};
}
}
아래는 글로벌 필터이다
@Slf4j
@Component
public class GlobalFilter extends AbstractGatewayFilterFactory<GlobalFilter.Config>{
@Data
public static class Config{
private String baseMessage;
private boolean preLogger;
private boolean postLogger;
}
public GlobalFilter() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange,chain) -> {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
log.info("Global 필터 메시지 : {}",config.getBaseMessage());
if(config.isPreLogger()) {
log.info("Global 필터 시작 request id = {}",request.getId());
}
return chain.filter(exchange).then(Mono.fromRunnable(() ->{
if(config.isPostLogger()) {
log.info("Global Post 필터 끝부분 response code = {}",response.getStatusCode());
}
}));
};
}
}
서버1 의 컨트롤러
@RequestMapping부분은 필수로 있어아야 한다
@Slf4j
@RestController
@RequestMapping("/first-service")// zuul는 없어도 됬는데 cloud일때는 잇어야함
public class FirstServiceController {
@GetMapping("/welcome")
public String welcome() {
return "welcom !!! first Service";
}
@GetMapping("message")
public String msg(@RequestHeader(value = "first-service",defaultValue = "NONE") String header) {
log.info("apigateway에서 추가한 헤더 정보"+header);
return header;
}
@GetMapping("/check")
public String check(HttpServletRequest request) {
log.info("check 호출됨");
log.info("요청 포트 : {}",request.getServerPort());
return "/check : "+request.getServerPort();
}
}
server:
port: 0
# port: 8081 포트 0번으로 하는 이유는 한곳에만 과부하가 걸리면 안되기때문에 로드밸런싱을 적용하기 위하여 포트번호를 랜덤으로 지정
spring:
application:
name: my-first-service
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka
instance:
instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
폼에 추가해줘야한다
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
서버2이다 내용은 1번과 동일하게 되어있다 굳이 볼필요는없다
@Slf4j
@RestController
@RequestMapping("/second-service")// zuul는 없어도 됬는데 cloud일때는 잇어야함
public class SecondServiceController {
@GetMapping("welcome")
public String welcom() {
return "welcom !!! second Service";
}
@GetMapping("message")
public String msg(@RequestHeader(name = "second-service",defaultValue = "NONE")String header) {
log.info("second"+header);
return header;
}
}
server:
port: 0
# port: 8082
spring:
application:
name: my-second-service
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:8761/eureka
instance:
instance-id: ${spring.application.name}:${spring.application.instance_id:${random.value}}
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
유레카 서버를 키게 되면 나오는 화면이다
게이트웨이 1개 서버1 서버1 총 3개가 접속되어있고
서버1 같은경우는 2개를 켜놨다
http://localhost:8000/first-service/check로 들어가게되면
랜덤으로 지정된 포트번호가 나온다
자세히 보면 위의 번호가 2개가 다르다
포트번호를 랜덤으로 지정해서 로드밸런싱을 구현했다
유레카가 구동중이고 변경이 있는지 계속 확인하고 있는 로그
필터부분이 적용되고 있는지 확인할수있는 부분
위에서 말했다 시피
유레카 서버 1개
게이트웨이 1개
1서버 2개
2서버 1개
가 켜져있다
'ETC' 카테고리의 다른 글
젠킨스로 CI/CD구축 (0) | 2023.08.21 |
---|---|
젠킨스 구축방법 (0) | 2023.08.09 |
oracle,mysql 타입 차이 (0) | 2023.07.14 |
도커 설정 (0) | 2023.07.10 |
파일질라 및 푸티 사용법 (0) | 2023.07.10 |