akka / erlang에서 액터를 사용하는 것이 좋지 않은 경우는 언제입니까?


58

나는 지금 매일 7-8 개월 동안 akka와 일하고있다. 시작했을 때 응용 프로그램을 작업하고 액터가 기본적으로 액터 시스템 내부에서 기본적으로 한 번만 사용되어 대부분의 객체 사이에서 통신한다는 것을 알았습니다. 그래서 나는 똑같이했습니다-x / y / z에 대한 다른 액터를 회전시킵니다.

나에게는 이것이 너무 무차별 적 일 수 있으며 필요하지 않은 곳에 복잡성을 추가하는 것처럼 보이지만 미래를 통한 액터 vs 일반 동기 또는 비동기 논리를 사용해야하는 곳에 대한 토론은 찾을 수 없습니다. 동료가 비슷한 말을 한 후에 나는 자세를 숙고하기 시작했습니다. 나는 최근에 작업을 숙고하고 불변의 구현에서 동일한 결과를 안전하게 얻을 수 있기 때문에 다른 행위자를 만드는 것을 피한 몇 가지 사례를 최근에 깨달았습니다. 예를 들어 DB 또는 파일에서 구성 값을 매우 드물게 액세스하는 곳과 같은 곳에서 얻는 것 결과는 실제 사용 사례입니다.

특히, 불변 상태로 플레이하는 경우 액터는 복잡성을 생성하고 처리량을 제한합니다. 예를 들어 객체의 순수한 함수는 동시성으로 모든 수준의 위험없이 동시에 호출 할 수 있습니다. 행위자는 한 번에 하나의 메시지 만 처리 할 수 ​​있습니다. 또 다른 고려 사항은 선물 사용을 시작하지 않는 한 결과를 기다려야하는 경우 스레드를 고정시키는 것입니다. 그러나 비동기 메시징 또는 스케일에 대해 걱정할 필요가없는 경우에는 액터를 사용하는 것이 과도하게 보일 수 있습니다.

내 질문은-배우를 사용하기에 나쁜 시간이 있습니까? 얼랭이 어떻게 생겼는지 궁금하고 다른 사람들의 통찰력을 정말로 좋아할 것입니다. 또는 배우 사용에 관한 몇 가지 원칙이있는 경우.


Akka와 매일 몇 달 동안 일할 수있는 직업은 무엇입니까?
Den

3
좋은 것. :) 또는 직접 변경하십시오.
JasonG

ask배우와 평범한 것을 사용하는 것의 트레이드 오프가 무엇인지 구체적으로 알고 싶습니다 Future.
Max Heiber

2
나는 몇 년 후 Akka에 관한 책을 쓰고 결국 다음과 같이 요약 할 수 있다고 생각합니다. 동기화 및 잠금 기능이 없습니다. 해당 상태를 액터에 넣으면 갑자기 안전하게 액세스되고 쓰기를 삭제하지 않거나 부실한 읽기를 얻지 못할 수 있습니다. 에를 랑과 아카의 배우는 상태가 나 빠지고 배우가 오류를 던질 수 있다고 가정하여 자체 치유 시스템 특성을 갖습니다. 변경이 필요없는 경우 선물은 더 간단합니다.
JasonG

몇 년 후 나는 erlang / elixir 프로그래머이고 새로운 통찰력을 가지고 이것을 다시 생각해 왔습니다. :) Elixir는 프로세스에 대한 대안으로서 객체가 없기 때문에 상당히 다릅니다. 따라서 상태 가 필요할 때 프로세스가 항상 빌드됩니다 . 그것은 동시에 발생합니다. 이것은 여전히 ​​최고의 휴리스틱입니다.
JasonG

답변:


23

이것은 내가 관심이 있고 몇 가지 연구를하고있는 질문입니다. 다른 관점 은 Noel Walsh 의이 블로그 게시물 또는 Stack Overflow에 관한 이 질문 을 참조하십시오 . 제안하고 싶은 의견이 있습니다.

  • Akka는 메시지와 함께 작동하기 때문에 "푸시 사고 방식"을 권장합니다. 종종 동시성을 위해 이것이 당신이 원하는 것이 아니라고 주장합니다. 당기기가 훨씬 안전합니다. 예를 들어 분산 시스템의 공통 패턴 중 하나 는 대기열에서 정보를 처리 하는 일련의 작업자를 갖는 것 입니다. 분명히 이것은 Akka에서 가능 하지만 반드시 사람들이 시도 하는 첫 번째 접근법 은 아닙니다 . Akka는 내구성이 뛰어난 사서함 을 제공 하지만 사용 방법에 따라 달라집니다. 단일 공유 대기열은 작업 균형 조정 / 재 할당 작업 당 대기열보다 훨씬 유연합니다.
  • 클래스를 배우로 대체하는 사고 방식에 쉽게 도달 할 수 있습니다. 사실 어떤 사람들은 배우가 한 가지만해야한다고 말함으로써 그것을 옹호하는 것처럼 보입니다 . 논리적 결론에 따르면 모든 클래스가 행위자라면 많은 추가 메시지와 수신 / 전송 블록이기 때문에 Jason이 설명하는 것처럼 코드 복잡성이 증가합니다. 또한 인터페이스의 형식을 잃기 때문에 코드를 이해하고 테스트하기가 더 어려워집니다. 주석이 이에 대한 해결책 이라고 확신하지 않습니다 . 또한 Akka의 전설적인 효율성 에도 불구하고 , 액터 확산은 성능면에서 현명한 아이디어가 아니라고 생각합니다. Java 스레드를 사용할 때 우리는 그들이 가치가 있고 그에 따라 보존한다는 것을 알고 있습니다.
  • 이전 요점과 관련이 있지만 또 다른 성가심은 Noel과 Pino가 강조하는 유형 정보의 손실입니다. 많은 사람들이 파이썬과 같은 다른 언어보다는 스칼라를 사용하는 이유입니다. 이이 주위에 몇 가지 방법입니다 그러나 그들은 중 하나입니다 표준이 아닌 , 하지 않는 것이 좋습니다 또는 실험 .
  • 마지막으로 "충돌" 사고 방식 이 있더라도 동시성 은 어렵습니다. 대체 프로그래밍 모델 은 도움이 될 수 있지만 문제를 해결하지는 못하고 변경합니다 . 따라서 공식적으로 생각하는 것이 좋습니다 . Joe Average 개발자가 RabbitMQ, Storm, Hadoop, Spark, Kafka 또는 NoSQL 데이터베이스와 같은 준비된 도구를 제공하는 이유이기도합니다. Akka는 사전 구축 된 도구와 구성 요소를 가지고 있지만 매우 낮은 수준으로 느껴지므로 분산 시스템의보다 준비된 공통 요소는 개발자가 시스템을 올바르게 구축하는 데 도움이됩니다.

제이슨처럼, 나는 다른 사람들의 통찰력을 듣고 싶어합니다. 위의 문제를 어떻게 해결하고 Akka를 더 잘 사용할 수 있습니까?


1
나는 Akka 스팟 온의 시험에 대한이 게시물을 발견 timgilbert.wordpress.com/2013/07/07/...
마크 버틀러

"상속성 구성"은 여전히 ​​의존성 주입에 유용합니다. 예를 들어, 의존성을 소품으로 전달하십시오 (생성자 매개 변수 사용). 문제는 감독이 될 것입니다. 생성 된 액터는 액터가 아닌 다른 곳에서 감독됩니다. 라우터는 최상위 레벨에서 생성 된 액터에 대한 감독 전략을 감싸는 데 사용될 수 있지만 지금은 매우 복잡합니다! 나는 케이크가 더 나은 해결책이라고 생각합니다-예를 들어 db 서비스 행위자를위한 행위자가 생성되는 특성이 있습니다. 그런 다음 텍스트 컨텍스트에서 테스트 모의 / 스텁 DB 서비스 특성을 사용하십시오.
JasonG

1
그렇습니다. 감독은 의존성 주입에서 제대로 작동하지 않습니다. 또한 클래스 대신 팩토리를 주입 해야하는 경우가 있었지만 그렇지 않은 경우 폐쇄 문제가 발생했습니다 .Akka의 스레드 처리로 인해 추측하고 있습니다.
Mark Butler

나는 그것이 나쁜 생각이 아니라고 생각합니다-고마워요-실제로 이것에 대해 조금 쓰고 사회화하려고 노력할 것입니다. 소품을주는 무언가를 주사 할 수 있습니까? 소비자가 액터를 인스턴스화 할 수있는 액터 팩토리. 예를 들어 def method (arg) = (psuedo?) 팩토리에서 Props (new ActorWithArgs (arg))를 반환하므로 액터를 올바른 컨텍스트에서 만들 수 있습니다. 이것은 di에 대한 케이크 솔루션에 대한 좋은 아이디어와 좋은 목표처럼 보입니다.
JasonG

나는이 과정을 다음과 같이 시작했다 : coursera.org/course/posa 그것은 주로 안드로이드를 프로그래밍하는 사람들을 목표로하지만 Java의 동시성에 대한 좋은 개요입니다. 그래서 제가 궁금한 점은 "Akka가 종소리와 휘파람을 가진 멋진 형태의 이벤트 루프가 아닌가 (이벤트 스레드를 다른 스레드에 넣을 수 있기 때문에) 아닌가?"입니다.
마크 버틀러

21

액터 모델이 어떤 용도로 사용되는지 고려해 볼 가치가 있습니다.

  1. 동시성 모델
  2. 가변 상태에 대한 동시 액세스를 피하는
  3. 비동기 통신 메커니즘을 사용하여 동시성을 제공합니다.

이는 여러 스레드에서 공유 상태를 사용하는 것이 매우 어려워지기 때문에 특히 동기화 상태를 유지해야하는 공유 상태의 여러 구성 요소간에 관계가있는 경우 매우 유용합니다. 그러나 다음과 같은 도메인 구성 요소가있는 경우 :

  • 동시성을 허용하지 않거나
  • 함수형 프로그래밍에서와 같이 변경 가능한 상태를 허용하지 않습니다. 또는
  • 일부 동기식 통신 메커니즘에 의존해야합니다.

액터 모델은 많은 이점을 제공하지 않습니다.

희망이 도움이됩니다.


고마워-변경 가능한 상태와 동시성이라는 두 가지 사항을 실제로 평가해야한다고 생각합니다. 클래스가 상태 비 저장이거나 동시성이 아닌 경우 해결할 문제가 없습니다. 한 가지 더 고려해야 할 사항-내결함성이 또 다른 포인트라고 생각합니까? 예를 들어 불변의 redis 클라이언트가 있지만 실행 중에 실패 할 수 있다면 좋은 사용 사례가 아닌가? 그 배우를 다시 시작해야 할 수도 있습니까? 클래스가 순전히 불변 일 수도 있지만 불변의 액터 외부에 손상된 상태가있을 수있어 클래스가 실패 할 수 있습니다.
JasonG

redis와의 통신을 담당하는 행위자는 예외가 발생하지만 다시 시작할 것이라고 생각합니다.
JasonG

@JasonG 내 생각에, "내결함성"은 일반적으로 액터 모델의 한 측면이 아니며, Erlang (그리고 아마도 Akka?)의 액터 모델 구현과 함께 제공되는 것입니다. redis와 대화 할 수는 없지만 "불변 클라이언트"가 이상하게 들린다 ... 소프트웨어 구성 요소가 실패 할 경우 어떻게 불변으로 간주되는지 알 수 없습니다.
Aidan Cully

내결함성과 감독은 akka에 있으며 erlang과 매우 유사합니다. 불변의 클라이언트에 대해 당신이 말하는 것을 이해하지만 불변은 코드 상태가 어디서나 변경되지 않는다는 것을 의미합니다. 시작시 연결을 초기화하면 모든 종류의 오류에 사용되는 재시작 전략으로 클라이언트 코드를 변경할 수 없으며 문제가 발생했을 때 액터를 다시 초기화하기 만하면됩니다.
JasonG

12

직감이 맞습니다, IMHO. 어디에서나 배우를 사용하는 것은 속담 망치를 가지고 손톱 만 보는 것과 같습니다.

Erlang 모범 사례는 동시에 발생하는 모든 활동에 프로세스 / 액터를 사용하는 것입니다. 즉, 실생활에서와 마찬가지로. 때로는 올바른 세분성을 찾기가 어렵지만 대부분의 경우 모델링 된 도메인을보고 약간의 상식을 사용하여 알 수 있습니다. 나는 그보다 더 좋은 방법이 없지만, 그것이 도움이되기를 바랍니다.


감사합니다. 이 토론에서 어떤 일이 일어나는지보고 싶습니다.
JasonG

0

입 / 출력 메시징 순서 :

나는 최근에 액터 모델이 실제로 동시성 문제를 일으킨 Akka 기반 응용 프로그램을 만났습니다.로드 할 때 더 간단한 모델이 더 좋았습니다.

문제는 들어오는 메시지가 다른 액터 경로를 통해 다른 '레인'으로 이동하고 있었지만 코드는 메시지가 도착한 순서대로 최종 목적지에 도착할 것이라고 가정했습니다. 데이터가 충분히 큰 간격으로 도착하는 한 대상과 충돌하는 메시지 충돌이 하나뿐이기 때문에 이것이 효과가있었습니다. 간격이 줄어들면 순서가 잘못되어 이상한 동작이 발생하기 시작했습니다.

약간 적은 액터로 문제를 올바르게 해결할 수 있었지만 과도하게 사용하면 쉽게 실수 할 수 있습니다.


이것은 기본적이고 광범위하게 관련되어 있습니다. 두 배우 간의 주문 만 보장 할 수 있습니다. doc.akka.io/docs/akka/current/scala/general/… 팬 아웃 / 인 시스템에서는 주문 배송을 보장 할 수 없습니다. andreasohlund.net/2012/01/18/dont-assume-message-ordering
JasonG

-1

제 생각에는 액터에 대한 두 가지 사용 사례가 있습니다. 포트 등과 같은 공유 리소스 및 큰 상태. 첫 번째는 지금까지 논의에 의해 잘 다루어졌지만, 큰 주 역시 타당한 이유입니다.

모든 프로 시저 호출과 함께 전달되는 큰 구조는 많은 스택을 사용할 수 있습니다. 이 상태는 별도의 프로세스, 프로세스 ID로 대체 된 구조 및 필요에 따라 쿼리 된 프로세스로 전환 될 수 있습니다.

기억 상실증과 같은 데이터베이스는 쿼리 프로세스 외부에 상태를 저장하는 것으로 생각할 수 있습니다.


1
당신은 명확히 할 수 있습니까? 네트워크에서 큰 상태를 의미합니까? 로컬 프로세스 내에서 불변 구조에 대한 참조를 전달하면 비용이 거의 들지 않으며 가변 구조를 전달할 수 없습니다. 송신하기 위해 복사해야하는 큰 가변 구조에 대해 이야기하고 있다고 가정합니까? 그래서 그것은 기본적으로 같은 상태입니다-공유 상태. 크기는 실제로 아무것도 변하지 않습니다. 오해인지 알려주세요.
JasonG

어떻게 참조로 전달합니까? 분명히 그렇게하는 방법은 구조를 프로세스에 넣고 프로세스 ID를 전달하는 것입니다. 로컬 호출은 데이터를 스택에 저장하고 모든 재귀 호출은 꼬리 재귀를 제외하고 다시 수행합니다. 한 호출에서 다른 호출로 상태를 전송하기위한 목록을 사용하여 구조의 재귀 처리를 수행 할 수 있으며이 상태는 다른 프로세스에서 구조를 참조 할 수 있습니다.
tony wallace
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.