2012-05-10 2 views
2

나는 심각한 두통을 불러 일으키는 레거시 RabbitMQ 코드를 물려 받았습니다. 아무도, "공식"설명서 어디로 비슷한 질문을 검색 할 수있는 가리키는 데 도움이 될 수 있습니까?RabbitMQ 멀티 스레드 채널 및 큐 바인딩

우리는 어떤 채널과 같이 채널을 사용하여 검색을 수행 노동자 응답을받을 만들 :

channelIn.queueDeclare("", false, false, true, null); 
channelIn.queueBind("", AmqpClient.NAME_EXCHANGE, 
    AmqpClient.ROUTING_KEY_ROOT_INCOMING + uniqueId); 

메일 링리스트와 포럼을 탐색에서 나의 이해는

  • 빈과 큐를 선언하는 것입니다 name은 서버가 고유 한 이름을 자동으로 생성하도록 허용하고
  • 대기열은 전역 적으로 고유 한 이름을 가져야합니다.

사실인가요?

위의 두 번째 줄에서 블로그와 메일 링리스트의 자유로운 해석에 기반한 나의 이해는 빈 큐 이름이있는 queuebind가 자동으로 마지막으로 생성 된 큐에 바인딩된다는 것입니다. 그때 당신은 clunky DeclareOK 객체에서 자동 생성 된 이름을 가져올 필요가 없기 때문에 좋을 것 같습니다.

사실인가요? 그렇다면 다중 스레드 환경에서 작동합니까?

e.e. 일부 채널이 다른 채널의 대기열에 자신을 바인딩 할 가능성이 있습니까? 그런 다음 다른 채널이 닫히면 올바르지 않게 바인드 된 채널에서 대기열을 사용하려고 할 때 오류가 발생합니까? (대기열은 autodelete = true로 작성되었음을 유의하십시오.) 테스트 결과 나는 예라고 생각하게되었지만 문제가있는 곳은 확신 할 수 없습니다.

답변

0

이것이 다중 스레드 환경에서 작동하는지 확신 할 수 없습니다. 시간의 높은 비율일지도 모르지만 잘못된 대기열을 가져올 수 있습니다. 위험을 감수하는 이유는 무엇입니까? 더 좋고 안전하지 않습니까?

String queueName = channelIn.queueDeclare("", false, false, true, null).getQueue(); 
channelIn.queueBind(queueName, AmqpClient.NAME_EXCHANGE, 
AmqpClient.ROUTING_KEY_ROOT_INCOMING + uniqueId); 

정확하지 않은 것은 아닙니다.

+0

정확합니다. 그다지 나쁘지 않습니다. 반환 개체를 사용하여 조회를 수행해야한다고 생각했습니다. 내 코드베이스에 다른 유사 항목이 있기 때문에 예상되는 동작이 무엇인지 알면 좋을 것입니다. – milletron

+0

유사한 퍼지 선이있는 경우, 나는 이와 같이 퍼지를 제거하는 방법을 찾는 데 우선 순위를 둡니다. 어쩌면 원래 코드가 이전 버전의 API 용으로 작성되었으며 이제 이러한 종류의 상황을 처리하는 더 나은 방법이있을 수 있습니다. 전반적으로 올바르게 사용된다면 rabbitMQ 클라이언트는 안전하게 스레드되어야합니다. – robthewolf

+0

오류 처리 방법, 연결이 닫히면 어떻게 될지, 채널을 두 번 열려고하면 어떤 문서 (예 : StackOverflow 게시물 및 RabbitMQ 목록이 아님)에 대한 포인터를 찾으려합니다. 사물의. 시행 착오를 거쳐 계속해서 물건들을 옮길 것입니다. – milletron

0

Q : 대기열이 이름없이 선언되면 어떻게됩니까?

A : 서버가 큐의 고유 한 이름을 선택합니다. 이름을 지정하지 않으면 RabbitMQ 서버가 RabbitMQ 클러스터 이름을 고유하게 생성하고 해당 이름의 대기열을 만든 다음 queue.declare이라는 클라이언트에 이름을 다시 전송합니다. RabbitMQ는 내부적으로 스레드로부터 안전한 방식으로이 작업을 수행합니다 (예 : queue.declare을 빈 이름으로 호출하는 많은 클라이언트가 동일한 이름을 갖지 않음). 이 동작에 대한 설명은 Here입니다.

Q : 대기열 이름은 전역 적으로 고유해야합니까?

대답 : 아니요.하지만 사용 사례에 있어야 할 수도 있습니다. 게시자와 구독자를 원하는 수만큼 제한 할 수 있습니다. 큐 선언은 멱등 (idempotent)합니다. 따라서 두 클라이언트가 같은 이름과 설정을 가진 큐를 동시에 또는 다른 시간에 선언하면 서버 상태는 하나만 선언 한 것과 같습니다. 그러나 빈 이름을 가진 대기열은 절대 충돌하지 않습니다.두 개의 연산 인 것처럼 빈 이름을 가진 큐를 선언하는 것을 고려하십시오. RabbitMQ에 "내 용도로만 사용할 전역 고유 이름을 지정하십시오"라고 묻는 RPC가 있고 그 이름을 가진 큐를 idempotently 선언합니다.

Q : 공백 이름을 가진 queue.bind은 멀티 스레드 환경에서 마지막으로 만들어진 대기열에 바인딩됩니까?

A : 예,하지만 그렇게해서는 안됩니다. 혼란스럽고 불특정/불완전한 행동을합니다.이 기술은 크게 의미가 없으며 클라이언트 코드의 버그가 발생하기 쉽습니다 (선언과 추가 사이에 행이 추가되는 경우 어떻게됩니까?) 그러면 어떤 큐가 바인딩되는지 결정하는 것이 매우 어려울 것입니다.

대신에 queueDeclare의 반환 값을 사용하십시오. 그 반환 값은 선언 된 대기열의 이름을 포함합니다. 이름이없는 대기열을 선언 한 경우 queueDeclare의 반환 값에는 RabbitMQ에서 제공 한 새로운 전역 고유 이름이 포함됩니다. 해당 대기열에서 작동하는 후속 호출 (예 : 바인딩과 같은)에이를 명시 적으로 제공 할 수 있습니다.

이 클라이언트는 큐의 이름을 지정하거나 이전 이 동일한의 큐를 선언해야한다 중 하나를 추가 이유는이 작업을 수행하지 않는

은 빈 대기열 이름 행동에 관한 documentation은 매우 모호 채널

그 의미는 무엇입니까? 하나 이상의 대기열이 선언 된 경우 어떤 대기열이 바인딩됩니까? 이전에 선언 된 대기열이 같은 채널에서 삭제 된 경우 어떻게됩니까? 가능한 한 명시 적이어야하며이 동작에 의존하지 않는 것이 매우 좋은 이유입니다.

Q : 큐가 연결된 "아래"채널에서 삭제 될 수 있습니까?

대답 : 예, 특정 상황입니다. 질문의 용어에 대한 약간의 설명 : 채널이 대기열에 "바인딩"되지 않습니다. 채널은 대기열을 소비 할 수 있습니다. 네트워크 피어와 같은 채널과 원격 피어와 같은 대기열을 생각해보십시오. 원격 피어에 포트를 바인딩하지 않지만 동일한 포트를 통해 둘 이상의 피어와 통화 할 수 있습니다. 소비자는 연결된 소켓과 동일합니다. 채널이 아닙니다. 어쨌든 :

채널은 여기에 상관 없지만 소비자와 연결은 채널당 동일한 대기열에 있어도 하나 이상의 소비자를 가질 수 있으며 연결 당 둘 이상의 채널을 가질 수 있습니다. 다음은 대기열을 구독하는 채널의 "아래"에서 삭제할 수있는 상황입니다 (일부는 놓쳤을 수 있지만 이는 모두 비파괴적인 것입니다 - 예 : "폭발 한 서버"조건) :

  1. 대기열은 exclusive이 true로 설정되고 대기열이 선언 된 연결으로 선언되었습니다. 대기열을 선언하는 데 사용 된 채널은 닫을 수 있지만 연결이 열려있는 한 대기열은 계속 존재합니다. 독점적 인 대기열에 연결된 클라이언트는 사라질 것입니다. 그러나 클라이언트가 선언자에게 "잠긴"경우 클라이언트가 우선 사용하기 위해 전용 대기열에 액세스하지 못할 수 있습니다 - the documentation은 배타적 잠금과 관련하여 "사용 된"의미를 명확히 알 수 없습니다.
  2. queue.delete 호출을 통해 수동으로 삭제 된 대기열입니다.이 경우 큐에 연결된 모든 사용자는 다음 번에 큐를 사용하려고 할 때 오류가 발생할 수 있습니다.

참고 많은 클라이언트 상황에서, 소비자는 종종 "수동" 충분히 그들이 큐가 사라 것을 깨닫게하지 않을 것을; 그들은 단지 무엇이 효과적으로 폐쇄 된 소켓인지 영원히 들어 줄 것입니다. 큐를 에 게시하거나 passive (존재하는 설문)으로 다시 선언하려고하면 존재하지 않는 것으로 나타납니다. 혼자만의 섭취량은 이 아닙니다. 때때로 "이 대기열이 삭제되었습니다!"라는 메시지가 나타납니다. 오류, 때때로 도착하기까지 몇 분 또는 몇 시간이 걸릴 수 있습니다. 가끔씩 은 소비하고있는 모든 작업에 오류가 표시되지 않습니다.

Q : 다른 소비자가 나올 때 auto_delete 대기열이 한 소비자에게 "삭제"됩니까?

A :auto_delete 큐가 마지막 소비자가 큐 잎 언젠가 후 삭제 번호. 따라서 auto_delete 대기열에서 두 명의 소비자를 시작하면 다른 대기열을 방해하지 않고 종료 할 수 있습니다. Here's 해당 동작에 대한 설명서를 참조하십시오.

또한 (per-queue TTL을 통해) 만료되는 대기열은 동일한 동작을 수행합니다. 대기열은 마지막 소비자가 떠난 후 언젠가 사라질 것입니다.