복붙노트

[SPRING] Spring 5의 Reactive Programming을 사용하여 웹 스레드의 최대 수를 실제로 "관리"하는 방법은 무엇입니까?

SPRING

Spring 5의 Reactive Programming을 사용하여 웹 스레드의 최대 수를 실제로 "관리"하는 방법은 무엇입니까?

고전적인 Tomcat 접근법을 사용할 때 서버가 사용자의 웹 요청을 처리하는 데 사용할 수있는 최대 스레드 수를 제공 할 수 있습니다. Reactive Programming 패러다임과 Reactor를 사용하여 우리는 수직으로 더 잘 확장 할 수 있으므로 최소한으로 차단됩니다.

그것은 동시 요청의 최대 수를 간단하게 정의하는 고전적인 Tomcat 접근 방식보다 관리하기 쉽지 않은 것으로 보인다. 동시 요청 수가 최대 일 때 응용 프로그램에서 필요로하는 최대 메모리를 쉽게 예측하고 그에 따라 확장 할 수 있습니다. Spring 5의 Reactive Programming을 사용할 때 이것은 더 많은 번거 로움처럼 보인다.

이 새로운 기술에 대해 sysadmin 친구들과 이야기 할 때, 그들은 RAM이 부족한 응용 프로그램이나 심지어 OS 수준의 스레드에 대한 걱정으로 회신합니다. 그러면 우리는 어떻게이 문제를 더 잘 처리 할 수 ​​있습니까?

해결법

  1. ==============================

    1.우선, 블로킹 작업이 없다면 동시성 관리를 위해 얼마나 많은 스레드를 제공해야하는지에 대해 걱정할 필요가 없습니다. 이 경우 모든 연결을 비동기 적으로 그리고 비 차단 적으로 처리하는 작업자는 단 한 명입니다. 그리고이 경우 우리는 쉽게 모든 연결을 경합 및 일관성없이 처리하는 연결 - 종업원을 확장 할 수 있습니다 (각 작업자는 자체 연결 큐를 가지며 각 작업자는 자체 CPU에서 작업합니다). 공유 된 디자인 없음).

    우선, 블로킹 작업이 없다면 동시성 관리를 위해 얼마나 많은 스레드를 제공해야하는지에 대해 걱정할 필요가 없습니다. 이 경우 모든 연결을 비동기 적으로 그리고 비 차단 적으로 처리하는 작업자는 단 한 명입니다. 그리고이 경우 우리는 쉽게 모든 연결을 경합 및 일관성없이 처리하는 연결 - 종업원을 확장 할 수 있습니다 (각 작업자는 자체 연결 큐를 가지며 각 작업자는 자체 CPU에서 작업합니다). 공유 된 디자인 없음).

    요약 :이 경우 Netty 또는 hybrid Undertow와 같은 서블릿이 아닌 서버의 경우 구성 애플리케이션 컨테이너 (Tomcat, WebSphere 등) 또는 이와 유사한 방식으로 이전과 동일하게 웹 스레드의 최대 수를 동일하게 관리합니다. 이익 - 당신은 더 많은 사용자 요청을 처리 할 수 ​​있지만 동일한 자원 소비로 처리 할 수 ​​있습니다.

    어떻게하면 I / O를 차단해야하는지에 대해, JDBC를 막는 DB에 대한 즉각적인 통신을 위해 가능한 한 응용 프로그램을 확장 가능하고 효율적으로 유지하는 가장 적절한 방법은 I / O 전용 스레드 풀을 사용해야합니다.

    먼저 JDBC 연결 풀에서 사용 가능한 연결과 동일한 양의 작업자로 스레드 풀을 만들어야합니다. 따라서 우리는 응답을 막히게 기다리는 쓰레드와 똑같은 양의 쓰레드를 가질 것이고 가능한 한 효율적으로 우리의 자원을 활용할 것입니다. 그래서 실제로 쓰레드 스택에 더 많은 메모리를 소비하지 않을 것입니다. 연결 모델).

    특성에 대한 액세스는 특정 데이터베이스와 JDBC 드라이버에 따라 다르므로 특정 구성에서 해당 구성을 외부화 할 수 있습니다. 이는 devops 또는 sysadmin에 의해 구성 될 수 있음을 의미합니다. Threadpool 구성 (이 예에서는 Project Reactor 3의 Scheduler 구성)은 다음과 같이 보일 수 있습니다.

    @Configuration
    public class ReactorJdbcSchedulerConfig {
        @Value("my.awasome.scheduler-size")
        int schedulerSize;
    
        @Bean
        public Scheduler jdbcScheduler() {
            return Schedulers.fromExecutor(new ForkJoinPool(schedulerSize));
            // similarly 
            // ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
            // taskExecutor.setCorePoolSize(schedulerSize);
            // taskExecutor.setMaxPoolSize(schedulerSize);
            // taskExecutor.setQueueCapacity(schedulerSize);
            // taskExecutor.initialize();
            // return Schedulres.fromExecutor(taskExecutor);
        }
    }
    ...
    
        @Autowire
        Scheduler jdbcScheduler;
    
    
        public Mono myJdbcInteractionIsolated(String id) {
             return Mono.fromCallable(() -> jpaRepo.findById(id))
                        .subscribeOn(jdbcScheduler)
                        .publishOn(Schedulers.single());
        }
    ...
    

    이 기법을 사용하여 공유 스레드 풀 구성을 외부 팀 (인스턴스의 경우 sysadmin)에 위임하고 생성 된 Java 스레드에 사용되는 메모리 사용을 관리 할 수 ​​있습니다.

    이 문은 I / O 스레드가 차단 대기중인 작업에만 있어야 함을 의미합니다. 결과적으로 스레드가 응답을 기다린 후에 결과 처리를 다른 스레드로 옮겨야합니다.

    그래서 위의 코드 스 니펫에서 .subscribeOn 바로 뒤에 .publishOn을 추가합니다.

    요약하자면,이 기술을 사용하여 스레드 풀 크기를 연결 풀 크기로 적절하게 제어하여 외부 팀이 응용 프로그램 크기를 관리하도록 허용 할 수 있습니다. 모든 결과 처리는 하나의 스레드 내에서 실행되므로 중복되지 않고 제어되지 않는 메모리가 소비되지 않습니다.

    이 경우 아무런 이익도 얻지 못하기 때문에 반응성 패러다임을 필요가 없습니다. 무엇보다도 Reactive Programming은 특히 RxJava 나 Project Reactor와 같은 Reactive 라이브러리를 사용한 기능적 기법의 사용에 대한 이해에서 특별한 마인드 쉬프트가 필요합니다. 차례 차례로 비 준비 사용자를 위해, 그것은 더 복잡을주고 더 많은 것 "무엇이 ****** 여기에서 계속되고 있는가"일으키는 원인이된다. 따라서 양쪽에서 작업을 차단하는 경우에는 여기에서 2 회 반응 형 프로그래밍이 실제로 필요하다고 생각해야합니다.

    또한 무료로 마술이 없습니다. Reactive Extensions는 많은 내부 복잡성과 함께 마술적인 .map, .flatMap 등을 사용하여 엔드 투 엔드 비 블로킹, 비동기 통신의 경우처럼 승리하는 대신 전반적인 성능과 메모리 소비를 잃을 수 있습니다 .

    즉 오래된 좋은 명령형 프로그래밍이 여기에 더 적합 할 것이고 이전의 좋은 Tomcat 구성 관리를 사용하여 메모리에서 애플리케이션 크기 조정을 훨씬 쉽게 제어 할 수 있습니다.

  2. from https://stackoverflow.com/questions/45416290/how-do-you-actually-manage-the-max-number-of-webthreads-using-spring-5s-react by cc-by-sa and MIT license