봄에 어떤 종류의 "이벤트 버스"를 이용합니까?빌트인, 리액터, 아카?
우리는 몇 주 후에 새로운 Spring 4 애플리케이션을 시작할 것입니다.이벤트 중심의 아키텍처를 사용하고 싶습니다.올해 저는 "리액터"에 대해 여기저기 읽었고, 웹에서 그것을 찾다가 우연히 "아카"를 발견했습니다.
지금은 세 가지 선택지가 있습니다.
ApplicationEvent
: http://docs.spring.io/spring/docs/4.0.0.RELEASE/javadoc-api/org/springframework/context/ApplicationEvent.htmlReactor
: https://github.com/reactor/reactor#reactorAkka
: http://akka.io/
저는 그것들의 실제 비교를 찾을 수 없었습니다.
지금은 다음과 같은 것이 필요합니다.
X
들을 수 있는 레지스터Event E
Y
들을 수 있는 레지스터Event E
Z
을 보냅니다.Event E
그리고 나서.X
그리고.Y
이벤트를 수신하고 처리합니다.
우리는 이것을 비동기식으로 사용할 가능성이 높지만, 몇 가지 동기식 시나리오도 분명히 있을 것입니다.또한 항상 클래스를 이벤트로 보냅니다. (Reactor 샘플은 대부분 String 및 String 패턴을 사용하지만 Object도 지원합니다.)
제가 이해한 바로는ApplicationEvent
기본적으로 동기식으로 작동합니다.Reactor
비동기식으로 작동합니다.Reactor
에서는 또를사수있다니습할을 도 있습니다.await()
동기식으로 만드는 방법.Akka
는 과거의동일기제공다니합능을한▁more다▁or▁same▁as▁provides▁less▁the와 다소 동일한 기능을 제공합니다.Reactor
원격 기능도 지원합니다.
await()
method: 여러 스레드가 완료될 때까지 기다릴 수 있습니까?아니면 그 실들의 일부라도?위의 예를 들어보면 다음과 같습니다.
X
들을 수 있는 레지스터Event E
Y
들을 수 있는 레지스터Event E
Z
을 보냅니다.Event E
다음과 같이 동기화할 수 있습니까?를 기다리다X
그리고. Y
완성할 수 있습니다.그리고 그것을 단지 기다리게 하는 것이 가능합니까?X
하지만 때문은 아닙니다.Y
?
어쩌면 다른 대안들도 있을까요?예를 들어 JMS는 어떻습니까?
많은 질문들이 있지만, 당신이 몇 가지 답을 제공할 수 있기를 바랍니다!
감사해요!
편집: 사용 사례 예
특정 이벤트가 발생하면 10000개의 이메일을 생성하고 싶습니다.모든 전자 메일은 사용자별 콘텐츠로 생성되어야 합니다.따라서 메일을 생성하고 발신자 스레드를 차단하지 않는 스레드(최대 = 시스템 CPU 코어)를 많이 만듭니다. 몇 분 정도 걸릴 수 있기 때문입니다.
특정 이벤트가 발생하면 알 수 없는 수의 서비스에서 정보를 수집하려고 합니다.각 가져오기에는 약 100ms가 소요됩니다.여기서 저는 원자로를 사용하는 것을 상상할 수 있습니다.
await
메인 스레드에서 작업을 계속하려면 그 정보가 필요하기 때문입니다.특정 이벤트가 발생하면 애플리케이션 구성을 기반으로 몇 가지 작업을 수행하려고 합니다.따라서 애플리케이션은 소비자/이벤트 핸들러를 동적으로 등록(해제)할 수 있어야 합니다.그들은 이벤트로 그들만의 일을 할 것이고 나는 상관하지 않습니다.그래서 저는 모든 핸들러를 위한 스레드를 만들고 메인 스레드에서 작업을 계속할 것입니다.
간단한 디커플링: 저는 기본적으로 모든 수신기를 알고 있지만, 제 코드에 있는 모든 수신기를 부르고 싶지는 않습니다.이 작업은 대부분 동시에 수행되어야 합니다.
스레드 풀 또는 링 버퍼가 필요한 것처럼 들립니다.이러한 프레임워크에는 필요에 따라 크기가 증가하는 동적 링 버퍼가 있습니까?
이 좁은 공간에서 당신의 질문에 제대로 대답할 수 있을지 모르겠습니다.하지만 한번 해볼게요! :)
ApplicationEvent
시스템과 원자로는 기능 면에서 매우 구별됩니다.ApplicationEvent
은 에유기합니다반로으에서 으로 합니다.ApplicationListener
그것보다 더 복잡한 것은 당신이 직접 논리를 구현해야 합니다(그러나 그것이 반드시 나쁜 것은 아닙니다).그러나 Reactor는 매우 가볍고 완전히 확장 가능한 포괄적인 라우팅 계층을 제공합니다.두 가지 기능의 유사성은 이벤트를 구독하고 게시할 수 있는 능력으로 끝나며, 이는 실제로 모든 이벤트 중심 시스템의 특징입니다.또한 새로운 것을 잊지 마세요.spring-messaging
스프링 4와 함께 모듈 출력.Spring Integration에서 사용할 수 있는 툴의 하위 집합이며 이벤트 중심 아키텍처를 구축하기 위한 추상화도 제공합니다.
Reactor를 사용하면 직접 관리해야 하는 몇 가지 주요 문제를 해결할 수 있습니다.
선택기 일치: 원자로가 일치합니다.Selector
한 다한일범단포는일치괄하를일치위(matching.equals(Object other)
자리 표시자 추출을 허용하는 보다 복잡한 URI 템플릿 일치로 호출합니다.또한 고유한 사용자 지정 논리를 사용하여 내장된 선택기를 확장하여 리치 개체를 알림 키(예: 도메인 개체)로 사용할 수 있습니다.
스트림 및 약속 API: 당신이 언급한 것은Promise
입니다..await()
메서드, 이는 차단 동작을 예상하는 기존 코드에 대한 것입니다.Reactor를 사용하여 새로운 코드를 작성할 때, 스레드를 차단하지 않음으로써 시스템 리소스를 효과적으로 활용하기 위해 구성과 콜백을 사용하는 것은 충분히 강조될 수 없습니다.대량의 작업을 실행하기 위해 적은 수의 스레드에 의존하는 아키텍처에서 호출자를 차단하는 것은 거의 좋은 생각이 아닙니다.미래는 단순히 클라우드 확장이 불가능하기 때문에 현대 애플리케이션이 대체 솔루션을 활용하는 이유입니다.
될 수 , 당의애플수있설만지계될,히직그찾저다당이것생니고합각라이을것을신는신속케이션리은으약솔트로스림나이▁the▁youration▁could'▁findll다▁promises▁you당ed▁think▁streams▁or▁either생▁with신,것니▁be▁architect▁i를 찾을 수 있을 것이라고 생각합니다.Stream
주요 연결할 수 .주요 이점은 API의 구성 가능성으로, 차단 없이 종속성 체인에서 작업을 함께 연결할 수 있습니다.이메일 사용 사례를 기반으로 한 완전한 즉석 사례로서 다음과 같이 설명합니다.
@Autowired
Environment env;
@Autowired
SmtpClient client;
// Using a ThreadPoolDispatcher
Deferred<DomainObject, Stream<DomainObject>> input = Streams.defer(env, THREAD_POOL);
input.compose()
.map(new Function<DomainObject, EmailTemplate>() {
public EmailTemplate apply(DomainObject in) {
// generate the email
return new EmailTemplate(in);
}
})
.consume(new Consumer<EmailTemplate>() {
public void accept(EmailTemplate email) {
// send the email
client.send(email);
}
});
// Publish input into Deferred
DomainObject obj = reader.readNext();
if(null != obj) {
input.accept(obj);
}
또한 원자로는 기본적으로 다음과 같은 경계를 제공합니다.CountDownLatch
임의의 소비자에 대한 차단을 위해 (따라서 당신은 구성할 필요가 없습니다.Promise
당신이 원하는 것이 단지 잠시 동안 차단하는 것이라면.Consumer
완료).날것을 사용할 수 있습니다.Reactor
그런 경우에 그리고 사용합니다.on()
그리고.notify()
서비스 상태 확인을 트리거하는 메서드입니다.
어떤에는, 은 하만어경는에우, 당이원는것은하신떤지인 것처럼 .Future
.ExecutorService
아니요? 그냥 단순하게 하는 게 어때요?원자로는 처리량 성능과 오버헤드 효율성이 중요한 상황에서만 실질적인 이점을 제공합니다.호출 스레드를 차단하는 경우에는 Reactor가 제공하는 효율성 향상 효과를 제거할 가능성이 높기 때문에 이러한 경우에는 더 전통적인 도구 세트를 사용하는 것이 좋습니다.
원자로의 개방성의 좋은 점은 두 가지가 상호작용하는 것을 막을 수 없다는 것입니다.자유롭게 섞을 수 있습니다.Futures
와 함께Consumers
구성 하십시오.이 경우 가장 느린 구성 요소만큼만 속도가 빨라질 수 있습니다.
요.ApplicationEvent
고객의 요구에 맞게 설계되지 않았기 때문입니다(라이프사이클 관리에 더 중점을 두고 있음).
당신이 알아내야 할 것은 당신이 그것을 하고 싶은지 여부입니다.
- 객체 지향 방식(즉, 행위자, 동적 소비자, 즉시 등록) 또는
- 서비스 방식(정적 소비자, 시작 시 등록됨).
합니다.X
그리고.Y
다음과 같은 경우:
- 일시적인 인스턴스(1) 또는 그들은
- 오래 지속된 싱글톤/서비스 물체(2)?
만약 당신이 즉석에서 소비자를 등록해야 한다면 Akka보다 더 좋은 선택입니다(저는 사용해본 적이 없어서 원자로에 대해 잘 모르겠습니다).만약 당신이 일시적인 개체에서 당신의 소비를 하고 싶지 않다면, 당신은 JMS나 AMQP를 사용할 수 있습니다.
여러분은 또한 이러한 종류의 도서관들이 두 가지 문제를 해결하기 위해 노력하고 있다는 것을 이해할 필요가 있습니다.
- 동시성(즉, 동일한 컴퓨터에서 병렬로 작업 수행)
- 배포(즉, 여러 대의 컴퓨터에서 병렬로 작업 수행
리액터와 아카는 주로 #1에 집중되어 있습니다.Akka는 최근 클러스터 지원을 추가했고 배우 추상화는 #2를 더 쉽게 합니다.메시지 큐(JMS, AMQP)는 #2에 초점을 맞춥니다.
저는 서비스 경로를 수행하고, 크게 수정된 Guava EventBus와 RabbitMQ를 사용합니다. 저는 Guava EventBus와 유사한 주석을 사용하지만 버스에서 전송되는 객체에 대한 주석도 가지고 있지만, 비동기 모드의 Guava EventBus를 POC로 사용한 다음 저처럼 직접 만들 수 있습니다.
역동적인 소비자(1)가 필요하다고 생각할 수 있지만 대부분의 문제는 간단한 펍/서브로 해결할 수 있습니다.또한 동적 소비자를 관리하는 것은 까다로울 수 있습니다. (따라서 Akka는 배우 모델이 이를 위한 모든 종류의 관리를 가지고 있기 때문에 좋은 선택입니다.)
프레임워크에서 원하는 것을 신중하게 정의합니다.프레임워크에 필요한 것보다 많은 기능이 있는 경우 항상 좋은 것은 아닙니다.더 많은 기능은 더 많은 버그, 더 많은 학습 코드, 그리고 더 적은 성능을 의미합니다.
우려해야 할 몇 가지 기능은 다음과 같습니다.
- 행위자의 성질(가벼운 물체 또는 가벼운 물체)
- 시스템 클러스터에서 작업할 수 있는 기능(Akka)
- 지속 메시지 대기열(JMS)
- 신호(정보가 없는 이벤트), 전환(다른 포트의 메시지를 복잡한 이벤트로 결합하는 개체, 페트리 네트 참조) 등과 같은 특정 기능.
wait와 같은 동기화 기능에 주의하십시오. 전체 스레드를 차단하고 스레드 풀에서 행위자가 실행될 때 위험합니다(스레드 기아).
더 많은 프레임워크:
포크 조인 풀 - 경우에 따라 허용await
굶주림 .
Java용 데이터 흐름 프레임워크 - 신호, 전환
애드온: 두 종류의 배우.
일반적으로 병렬 작업 시스템은 활성 노드가 서로 메시지를 보내는 그래프로 나타낼 수 있습니다.대부분의 다른 메인스트림 언어와 마찬가지로 Java에서는 활성 노드(액터)를 스레드 또는 스레드 풀에 의해 실행되는 태스크(실행 가능 또는 호출 가능)로 구현할 수 있습니다.일반적으로 배우의 일부는 스레드이고 일부는 태스크입니다.두 가지 접근 방식 모두 장단점이 있으므로 시스템의 각 행위자에 가장 적합한 구현을 선택하는 것이 중요합니다.간단히 말해 스레드는 차단(및 이벤트 대기)할 수 있지만 스택에 많은 메모리를 사용합니다.작업은 차단할 수 없지만 공유 스택(풀의 스레드)을 사용할 수 있습니다.
작업에서 차단 작업을 호출하면 풀링된 스레드가 서비스에서 제외됩니다.많은 작업이 차단되면 모든 스레드를 제외하여 교착 상태를 초래할 수 있습니다. 차단된 작업을 차단 해제할 수 있는 작업은 실행할 수 없습니다.이러한 교착 상태를 스레드 기아라고 합니다.스레드 부족을 방지하기 위해 스레드 풀을 무제한으로 구성하면 작업을 스레드로 변환하여 작업의 이점을 잃게 됩니다.
작업에서 차단 작업에 대한 호출을 제거하려면 작업을 차단하는 두 개 이상의 작업 호출로 분할해야 합니다. 첫 번째 작업 호출은 작업을 차단하고 종료하고 나머지는 차단 작업이 완료될 때 시작되는 비동기 작업으로 형식을 지정해야 합니다.물론 차단 작업에는 대체 비동기 인터페이스가 있어야 합니다.따라서 예를 들어 소켓을 동시에 읽는 대신 NIO 또는 NIO2 라이브러리를 사용해야 합니다.
안타깝게도 표준 Java 라이브러리에는 대기열 및 세마포와 같은 일반적인 동기화 기능을 위한 비동기식 라이브러리가 없습니다.다행히 처음부터 쉽게 구현할 수 있습니다(예는 Java용 Dataflow 프레임워크 참조).
따라서, 순수하게 비차단 작업으로 계산하는 것은 가능하지만 코드의 크기를 증가시킵니다.가능한 경우 스레드를 사용하고 단순한 대규모 계산에만 작업을 수행하는 것이 좋습니다.
언급URL : https://stackoverflow.com/questions/20663988/what-kind-of-eventbus-to-use-in-spring-built-in-reactor-akka
'bestsource' 카테고리의 다른 글
심포니 만들기:마이그레이션: 메타데이터 저장소가 최신이 아닙니다. 이 문제를 해결하려면 sync-metadata-storage 명령을 실행하십시오. (0) | 2023.08.12 |
---|---|
JavaScript로 브라우저에서 Android 전화기 회전 감지 (0) | 2023.08.12 |
Jquery 코드는 머리글에 넣어야 합니까 아니면 바닥글에 넣어야 합니까? (0) | 2023.08.12 |
별도의 스레드에서 실행되는 iphoneios (0) | 2023.08.12 |
판다/파이썬에서 엑셀 스프레드시트의 공식을 보려면 어떻게 해야 합니까? (0) | 2023.08.12 |