• Reactor_part3

    Spring Webflux Spring Webflux 탄생 배경 Spring MBC의 한계 Servlet 기반의 Blocking IO 방식 하나의 요청을 사용하기 위해 하나의 스레드를 사용하고, 해당 스레드의 작업이 끝나기 전까지 스레드는 block 된다. 대량의 요청을 안정적으로 처리하기 위해 Non-Blocking 형태의 Spring Webflux 탄생 Webflux 기술 스택 Servlet Containers <-> Netty Servlet 3.1+ Containers Servlet API <-> Reactive Streams Adapter Spring Security <-> Spring Security Reactive Spring MVC <-> Spring Webflux Spring Data Reposiotries(JDBC, JPA, NoSQL) <-> Spring Data Reactive Repository(R2DBC, NoSQL) 서버 Spring MVC는 Tomcat과 같이 Servlet Container에서 Blocking IO 방식으로 동작 Webflux는 Non Blocking을 동작하는 Netty 등의 서버 엔진 사용 서버 API Webflux는 기본 서버 엔진이 Netty 지만, Jetty나 Undertow 같은 서버 엔진에서 지원하는 리액티브 스트림즈 어댑터를 통해 리액티브 스트림즈 지원 보안 WebFilter를 이용해 Spring Security를 Webflux에서 사용할 수 있다. 데이터 액세스 Non-Blocking IO를 지원할 수 있도록 R2DBC 및 NoSQL 모듈 사용 요청 처리 흐름 최초에 요청이 들어오면 Netty 등의 서버 엔진을 거쳐 HttpHandler가 전달 받는다. Handler는 다양한 서버 엔진을 지원할 수 있도록 추상화해주는 역할 a. 각 서버엔진마다 주어지는 ServerHttpRequest, ServerHttpResponse를 포함하는 ServerWebExchange를 생성한 후 WebFilter 전달 ServerWebExchange는 WebFilter 체인에서 전처리 과정을 거친 후, WebHandler 인터페이스 구현체인 DispatcherHandler에게 전달 DispatcherServlet과 유사한 역할을 하는 Dispatcher Handler에서는 HandlerMapping List를 원본 Flux의 소스로 전달 받는다. ServerWebExchange를 처리할 핸들러를 조회 조회한 핸들러의 호출을 HandlerAdapter에게 위임 HandlerAdapter는 ServerWebExchange를 처리할 핸들러 호출 Controller 또는 HandlerFunction 형태의 핸들러에서 요청을 처리한 후 응답 데이터를 리턴 핸들러로부터 리턴받은 응답 데이터를 처리할 HandlerResultHandler를 조회 조회한 HandlerResultHandler가 응답 데이터를 처리한 후 response 리턴 핵심 컴포넌트 HttpHandler public interface HttpHandler { Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response); } public class HttpWebHandlerAdapter extends WebHandlerDecorator implements HttpHandler { Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) { // ... ServerWebExchane exchange = createExchange(request, response); // ... } } WebFilter public interface WebFilter { Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain); } @Component public class BookLogFilter implements WebFilter { Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { String path = exchange.getRequest().getURI().getPath(); return chain.filter(exchange).doAfterTerminate(() -> { if(path.contains("books") { System.out.println("path: " + path); } }); } } } Servlet Filter 처럼 핸들러가 요청을 처리하기 전에 전처리 작업을 할 수 있도록 해준다. WebFilterChain을 통해 필터 체인을 형성하여 원하는 만큼의 필터를 추가할 수 있다. HandlerFilterFunction @FuntionalInterface public interface HandlerFilterFunction<T extends ServerResquest, R extends ServerResponse> { Mono<R> filter(ServerWebRequest request, HandlerFunction<T> next); /// } public class BookRouterFunctionFilter implements HandlerFilterFunction { @Override Mono<R> filter(ServerWebRequest request, HandlerFunction<T> next) { String path = exchange.getRequest().getURI().getPath(); return next.handler(exchange).doAfterTerminate(() -> { if(path.contains("books") { System.out.println("path: " + path); } }); } } @Configuration public class BookRouterFunction { return RouterFunctions .route(GET("v1/router/books/{bookId}), (ServerRequest) request -> this.getBook(request)) .filter(new BookRouterFunctionFilter()); } 함수형 기반의 요청 핸들러에 적용할 수 있는 Filter WebFilter 구현체는 Spring Bean으로 등록되는 반면 HandlerFilterFunction 구현체는 애너테이션 기반의 핸들러가 아닌 함수형 기반의 요청 핸들러에서 함수 형태로 사용되기 때문에 bean으로 동작하지 않는다. DispatcherHandler WebHandler 구현체로 Front Controller 패턴이 적용되어 먼저 요청을 전달받은 후 다른 컴포넌트에 요청 처리 위임 DispatchHandler 자체가 Bean으로 등록되어 동작하며, HandlerMapping, HandlerAdapter, HandlerResultHandler 등의 요청 처리를 위한 위임 컴포넌트 검색 HandlerMapping public interface HandlerMapping { Mono<Object> getHandler(ServerWebExchange exchange); } MVC와 동일하게 request와 handler object에 대한 매핑을 정의하는 인터페이스이며, HandlerMapping 인터페이스를 구현하는 구현클래스로 RequestMappingHandlerMapping, RouterFunctionMapping 등이 있다. HandlerAdapter public interface HandlerAdapter { boolean supports(Object handler); // 파라미터로 전달받은 handler object를 지원하는지 체크 Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler); // 파라미터로 전달받은 handler object를 통해 핸들러 메서드 호출 } HandlerMapping을 통해 얻은 핸들러를 직접 호출하는 역할을 하며 HandlerResult를 리턴받는다. RequestMappingHandlerAdapter, HandlerFunctionAdapter, SimpleHandlerAdapter, WebSocketHandlerAdapter 존재 Non-Blocking 프로세스 구조 Blocking IO 방식의 MVC는 요청을 처리하는 스레드가 차단될 수 있기 떄문에 기본적으로 대용량의 스레드 풀을 사용해 하나의 요청을 하나의 스레드가 처리 NonBlocking IO 방식은 WebFlux는 스레드가 차단되지 않기 때문에 적은 수의 고정된 스레드 풀을 사용해 더 많은 요청을 처리 스레드 차단 없이 더 많은 요청을 처리할 수 있는 이유는 Event Loop 방식 때문 요청을 요청 핸들러가 전달받는다. 전달받은 요청을 이벤트 루프에 푸시하면 이벤트 루프는 네트워크, DB 연결 작업 등 비용이 드는 작업에 대한 콜백 등록 작업이 완료되면 완료 이벤트를 이벤트 루프에 푸쉬 등록한 콜백을 호출해 처리 결과 전달 요청 처리, DB 연결과 같은 IO 작업을 이벤트로 처리하기 때문에 이벤트에 대한 콜백을 등록하고 동시에 다음 이벤트 처리로 넘어간다. 스레드 모델 NonBlocking IO를 지원하는 Netty등의 서버 엔진에서 작은 수의 고정된 크기의 스레드를 생성하여 대량의 요청 처리 Reactor Netty에서는 CPU 코어의 개수가 4보다 작은 경우 최소 4개의 워커 스레드를 생성하고, 4보다 더 많다면 코어 개수만큼 스레드 생성 적은 수의 스레드로 대량의 요청을 효과적으로 처리할 수 있다. 클라이언트 요청부터 응답 처리과정 안에서 Blocking되는 지점이 존재한다면 오히려 성능이 저하된다. Scheduler 를 통해 서버 엔진에서 제공하는 스레드 풀이 아닌 다른 스레드 풀을 사용한다.
  • Reactor_part2

    Project Reactor
  • Kafka - MessageListener와 @KafkaListener Annotation

    MessageListener
  • Springr2dbc

    Spring Data R2DBC
  • Java 9부터 17까지

    Spring Framework 6.0, Spring Boot 3.0 에서 Java 17 버전을 선택하여 9 버전 이후부터 업데이트 된 내용을 확인하고자 한다. [Preparing for Spring Boot 3.0](https://spring.io/blog/2022/05/24/preparing-for-spring-boot-3-0) Java 11(LTS) 까지의 업데이트 Java 9 Jigsaw module system 참고:Baeldung 라이브러리와 규모가 큰 시스템을 모듈화하고 강력한 접근 제어를 통해 느슨한 결합, 모듈 간 결합 방지, 보안성 향상 등에 이점을 갖는다 JPMS(Java Platform Module System)의 일환으로 JRE를 작은 단위 모듈로 쪼개고 사용하는 모듈만 패키징하여 배포 가능(module-info.java) JShell(The Java Shell (Read-Eval-Print Loop)) Tool script 형태로 Main Method 없이 즉석에서 실행 가능한 도구 jlink(The Java Linker) 최근에는 JDK만 제공하고 JRE는 제공하고 있지 않기 떄문에 필요시 jlink 기능을 사용하여 추출 가능 Immutable Set(of) Set<String> keySet = Set.of("key1", "key2", "key3") Optional.stream() List<String> filteredList = listOfOptionals.stream() .flatMap(Optional::stream) .collect(Collectors.toList()); Interface private method 도입 @FunctionalInterface public interface PrivateMethodInterface { private static String staticPrivate() { return "Static Private"; } private String instancePrivate() { return "Instance Private"; } void printPrivateMethod(); default void check() { String result = staticPrivate(); PrivateMethodInterface privateMethodInterface = () -> { System.out.println(this.instancePrivate()); }; privateMethodInterface.printPrivateMethod(); result = privateMethodInterface.instancePrivate(); } } New HTTP Client java.net.http 패키지하에 있는 신규 API로 HTTP/2 프로토콜, 웹소켓을 지원한다 ```java HttpRequest request = HttpRequest.newBuilder() .uri(new URI(“http://localhost:8080/members”)) .GET() .build();
  • Spring Proxy Bean

    Spring Bean은 Proxy로 만들어질까?
  • 네트워크 프로그래밍 07. 네트워크 확장성

    네트워크 확장성
  • 네트워크 프로그래밍 06. UDP와 멀티캐스팅

    UDP와 멀티캐스팅 UDP(User Datagram Protocol)은 TCP에 비교해 패킷이 의도한 목적지에 도착한다는 보장, 순서의 보장을 할 수 없기 때문에 신뢰할 수 없다. 비연결 프로토콜로 패킷 전송을 용이하게 하는 두개의 노드간의 메시지 교환이 없다. DNS, NTP, VOIP, P2P 네트워크에서 네트워크 통신의 조정, 비디오 스트리밍 등에 사용된다
  • Kafka - 운영 시 고려사항

    토픽과 파티션
  • Kafka 스트림즈

    카프카 스트림즈
  • 1
  • 2