2017-11-21 20 views
0

초기 요청을 받고, 일부 처리를 수행 한 다음 다른 서비스에 일부 요청/할일을 보내는 복잡한 백엔드 서비스에 actors을 어떻게 사용할 수 있습니까? 최종 결과를 계산할 때까지 일부 응답을 기다리고 응답을 기반으로 계속하는 방법을 결정하는 등의 작업을 수행 할 수 있습니다.실제로 행위자를 사용하는 곳과 방법

이러한 서비스를 구현하기 위해 액터를 사용하려고하면 다음과 같은 질문이 제기됩니다. 액터가이 워크 플로우의 어떤 부분을 구현해야하며 어떤 부분을 구현하면 안됩니까?

액터 인스턴스는 수행하려고하는 작업이 완료 될 때까지 사용중인 스레드를 릴리스하지 않습니다 (우리가 Future에 위임하지 않는 한). 따라서 전체 워크 플로를 더 작게 계층 구조로 작성하는 것처럼 보입니다 N 계층의 어린이가있는 작은 액터는 액터 컨셉에 기반한 이상적인 디자인이지만 다른 한편으로는 N-1 스레드 (초기 요청 당)를 유지합니다. 완료 할 계층 구조의 맨 아래에있는 배우 중 한 명이됩니다. 특히 계층 구조의 최상위 액터는 대부분 유휴 상태입니다.

이 계층 구조 디자인은 error kernel 패턴과도 일치합니다.

그러나 이것은 동시성에 매우 나쁜 것처럼 들립니다.

비록이 액터의 계층 구조를 유지하려고 시도했지만 미래에 각 액터에 전화를 걸기를 원한다고해도 (말하기보다는 자식 액터에게 묻기 때문에) 잠금이 훨씬 짧습니다) - 너무 많은 Futures에서 여전히 작업하면서 상태 보존 형 액터, 또는 스스로 동기화되지 않는 방식으로 시스템의 상태를 수정하는 행위자 (즉, 간단히 데이터베이스를 수정하지 않고 최소한 간단한 요청 만 수행하는 행위자)와 작업하는 것은 불가능합니다. 데이터베이스 트랜잭션을 통해 자동으로 - 응용 프로그램의 일부 전역 변수 수정).

따라서 액터는 하위 수준의 워크 플로에서만 사용해야합니까?

대부분 계층 적이며 (대부분은 그렇습니다) 직렬 방식으로 다시 작성해야하므로 많은 수준의 하위 액터가 필요하지 않습니다 (하지만 이는 매우 어렵고 부자연 스럽습니다. 구현 프레임 워크가 설계에 너무 많은 영향을 미침).

그렇다면 행위자는 매우 제한적이며 실패 내성은 주로 전통적인 예외 처리에 의해 처리되어야한다는 것을 의미하며 어떤 경우에도 내결함성이있는 응용 프로그램을 보유하려는 욕구는 그다지 영향을 미치지 않아야합니다 응용 프로그램의 디자인 그런 경우 배우와 함께 왜 귀찮게합니까? 복잡한 스파게티 같은 매듭의 메시지 흐름을 이해하기 위해 모든 액터의 구현을 읽는 프레임 워크로 작업하는 것은 원하는 범위로 공개 될 수있는 계층 적 구조를 기반으로하는 프레임 워크로 작업하는 것보다 훨씬 쉽습니다. 반드시 구현을 들여다 보지 않아도 메소드 시그니처를 살펴볼 수 있습니다.

쉬운 스케일링과 같은 액터의 많은 이점은 액터가 애플리케이션의 일부만을 구현하는 경우 관련성이 낮거나 실용적인 것으로 보입니다.

답변

0

액터의 "잠금"에 대한 이해가 잘못되었습니다.

당신은

를 작성하지만, 다른 한편으로는 (초기 요청에 따라) N-1 스레드까지 계속 것입니다 - 계속 여기에 설명 된 시나리오 아무것도

그것은 불분명하지 않는 것 잠겨 . 사용되는 스레드 수는 액터의 계층 또는 액터 계층 구조의 레이어 수에 의해 결정되지 않지만 액터를 실행하는 디스패처에 의해 결정됩니다. https://doc.akka.io/docs/akka/2.5/dispatchers.html?language=scala

액터는 일반적으로 새 스레드를 생성하거나 블록하지 않습니다 유휴 상태 일 때. 그것은 (구성 가능한) 메시지 수를 처리 한 다음 발송자에게 다시 통제권을 양보합니다. 따라서 멀티 스레딩의 관점에서 볼 때, Akka는 의심되는 것과는 달리 매우 효율적입니다. 당신이 너무 짧은 것 잠금, (자식 배우보다는 이야기를 물어) 배우의 계층 구조를 유지하지만, Future를 각 배우에 전화를 포장하려고하면

거기에 약간의 오해가 있어야합니다. 메시지를 다른 사람에게 보내는 액터는 스레드를 차단하지 않습니다. 당신이 참조하는 "고정"이 무엇인지는 명확하지 않습니다. 또한, 잠금이 없으므로 ask은 잠금을 짧게한다는 가정에 결함이있는 것은 분명합니다.

아마도 배우의 IO 차단 사용에 대해 걱정할 필요가있을 것 같습니다. 실제로 실행 스레드가 차단됩니다. 여기서 "트릭"은 차단 호출을 별도의 디스패처에 넣는 것입니다. https://doc.akka.io/docs/akka/snapshot/dispatchers.html?language=scala

+0

초기 메시지는 최상위 액터 A로 보내집니다. 처리하려면 스레드 A가 액터 A에 할당됩니다. 처리하는 동안 액터 A는 자식 행위자 B 중 한 명에게 질문합니다.이 질문을 처리하기 위해 B 스레드는 B 배우에게 할당됩니다. Actor A는 초기 메시지 처리 방법을 결정하기 위해 B 배우의 대답이 필요합니다. 이 모든 시간 동안 스레드 A와 B가 사용 중입니다. 이 시간의 대부분은 스레드 A가 유휴 상태입니다. 배우 B의 자녀와 손자 등이이 과정을 반복 할 수 있습니다. 내 이해에 문제가 있니? – rapt

+0

예. 모든 액터 A가 B에게 메시지를 보낸 후에는 남은 것이 없으므로 스레드 A가 자유로 워서 다른 것을 처리하게됩니다. 이제 배우 A가 완료되었습니다. B 자체가 완료되면 A에게 메시지를 보내면 A가 다른 스레드 (A, B 또는 일부 다른 스레드 일 수 있음)에서 다시 실행됩니다. 이것은 행위자 계층 구조에 독립적이며, B가 A의 자식인지 아닌지에 대한 고려 사항은 없다. 하위 배우는 하위 스레드를 의미하지 않습니다. – lutzh

+0

당신은 실제로 배우 (또는 Akka 구현)가 심각한 문제를 가지고 있다는 나의 의혹을 확인했다고 생각합니다. 아니요, 배우 A가 지금 완료되지 않았습니다. 나는 명시 적으로 "배우 A가 초기 메시지 처리 방법을 결정하기 위해 배우 B의 대답을 필요로합니다."라고 말했습니다. 액터는 하나의 메시지 처리 중에 둘 이상의 메시지를 보낼 수 있습니다. 제 경우에는 매우 일반적입니다. 추가 메시지는 먼저 액터 B의 응답을 받아야 계속 진행할 수 있습니다. 그래서 계속하기 전에 스레드 A가 미래 B가 완료 될 때까지 대기 상태로 유지하는 이유입니다. – rapt