RabbitMQ와 채널과 연결의 관계


176

RabbitMQ 자바 클라이언트는 다음과 같은 개념이 있습니다 :

  • Connection -RabbitMQ 서버 인스턴스에 대한 연결
  • Channel -???
  • 소비자 스레드 풀-RabbitMQ 서버 큐에서 메시지를 소비하는 스레드 풀
  • 큐-FIFO 순서로 메시지를 보유하는 구조

나는 관계를 이해하기 위해 노력하고있어 더 중요한과연관성 그들 사이.

  1. 나는 Channel이것이 당신이 게시하고 소비하는 구조이고 개방 된 연결에서 생성된다는 사실을 제외하고는 무엇인지 확실하지 않습니다 . 누군가가 "채널"이 무엇을 나타내는 지 설명 할 수 있다면 몇 가지를 정리하는 데 도움이 될 수 있습니다.
  2. 채널과 큐의 관계는 무엇입니까? 동일한 채널을 사용하여 여러 큐와 통신 할 수 있습니까, 아니면 1 : 1이어야합니까?
  3. 큐와 소비자 풀의 관계는 무엇입니까? 여러 소비자를 동일한 대기열에 가입 할 수 있습니까? 동일한 소비자가 여러 대기열을 사용할 수 있습니까? 아니면 관계가 1 : 1입니까?

도움을 주셔서 감사합니다.


이 질문에 대한 답변으로 여기에 질문하는 대신 golang 클라이언트 로이 문제 를 보고하게 되었습니다.
브루스 아담스

채널은 클라이언트와 노드 사이의 단일 물리적 TCP 연결을 다중화하는 데 사용되는 논리적 개념입니다. 채널 번호는 AMQP 프레임의 메시지 헤더에 포함됩니다.
ymas

답변:


196
  1. A Connection는 메시지 브로커에 대한 실제 TCP 연결을 나타내며 a Channel는 내부의 가상 연결 (AMQP 연결)입니다. 이 방법으로 TCP 연결로 브로커를 오버로드하지 않고도 애플리케이션 내에서 원하는만큼 (가상) 연결을 사용할 수 있습니다.

  2. Channel모든 것을 위해 하나 를 사용할 수 있습니다 . 그러나 스레드가 여러 개인 경우 Channel각 스레드마다 다른 스레드 를 사용하는 것이 좋습니다 .

    Java 클라이언트 API 안내서의 채널 스레드 안전성 :

    채널 인스턴스는 여러 스레드에서 안전하게 사용할 수 있습니다. 채널에 대한 요청은 직렬화되며 한 번에 하나의 스레드 만 채널에서 명령을 실행할 수 있습니다. 그럼에도 불구하고 응용 프로그램은 여러 스레드에서 동일한 채널을 공유하는 대신 스레드 당 채널을 사용하는 것을 선호해야합니다.

    사이에 직접적인 관계가 없다 Channel하고 Queue. A Channel는 AMQP 명령을 브로커로 보내는 데 사용됩니다. 이것은 대기열 또는 이와 유사한 생성 일 수 있지만 이러한 개념은 서로 연결되어 있지 않습니다.

  3. 각각 Consumer은 소비자 스레드 풀에서 할당 된 자체 스레드에서 실행됩니다. 여러 소비자가 동일한 대기열에 가입 한 경우 브로커는 라운드 로빈을 사용하여 메시지를 동일하게 분산시킵니다. 학습서 2 : "작업 큐"를 참조하십시오 .

    Consumer여러 대기열에 동일 하게 연결할 수도 있습니다 . 소비자를 콜백으로 이해할 수 있습니다. 소비자가 바인드 된 큐에 메시지가 도착할 때마다 호출됩니다. Java 클라이언트의 경우 각 소비자는 handleDelivery(...)콜백 메소드를 나타내는 method를 갖습니다 . 일반적으로 서브 클래스 DefaultConsumer및 재정의를 수행 handleDelivery(...)합니다. 참고 : 동일한 Consumer 인스턴스를 여러 큐에 연결하면이 메소드는 다른 스레드에 의해 호출됩니다. 필요한 경우 동기화를 관리하십시오.


4
설명서에서 추가하기 만하면 : 소비자에 대한 콜백은 Connection에서 관리하는 스레드와 별개의 스레드에서 발송됩니다. 이는 소비자가 연결 또는 채널에서 queueDeclare, txCommit, basicCancel 또는 basicPublish와 같은 차단 방법을 안전하게 호출 할 수 있음을 의미합니다. 각 채널에는 자체 디스패치 스레드가 있습니다. 채널당 하나의 소비자가 가장 일반적으로 사용하는 경우 소비자는 다른 소비자를 보유하지 않습니다. 채널당 여러 소비자가있는 경우 장기 실행 소비자는 해당 채널의 다른 소비자에게 콜백 발송을 보류 할 수 있습니다.
filip

1
동일한 소비자 인스턴스를 동일한 채널의 여러 대기열에 연결하면 콜백이 동일한 스레드에서 발송됩니다. 이 경우 동기화가 필요하지 않습니까?
filip

연결 풀 대신 하나의 연결 만 사용하고 채널 풀을 사용할 수 있습니까? 이것이 메시지 게시 처리량에 영향을 줍니까?
qeek

4
Java 클라이언트 API에 대한이 참조는 구식이며 실제로 오늘날의 참조는이 답변의 인용문과 직접적으로 모순됩니다. 오늘의 언급에 따르면 "채널 인스턴스를 스레드간에 공유해서는 안됩니다"라고합니다.
Edwin Dalorzo

1
@ EdwinDalorzo-처음에 문서를 작성한 사람은 채널 연결 이분법을 완전히 이해하지 못한 것처럼 보입니다. AMQP 0.9.1의 기본 아키텍처는 실제로 채널을 세션으로 취급하므로 세션을 공유하는 다른 스레드는 실제로 의미가 없습니다. 제 생각 엔 그것이 변화의 이유입니다.
theMayer

53

AMQP 프로토콜이 "후드에서"수행하는 작업에 대한 개념을 잘 이해하면 유용합니다. AMQP 0.9.1이 배포하기로 선택한 문서와 API가 특히 혼란스러워서 많은 사람들이 씨름해야 할 문제입니다.

TL; DR

연결 AMQP 서버와 물리적 협상 TCP 소켓입니다. 올바르게 구현 된 클라이언트는 애플리케이션별로 스레드 안전하고 스레드간에 공유 할 수있는 애플리케이션 당 하나를 갖습니다.

채널 연결에 단일 애플리케이션 세션입니다. 스레드에는 이러한 세션 중 하나 이상이 있습니다. AMQP 아키텍처 0.9.1은 스레드간에 공유되지 않아야하며 스레드를 작성한 스레드가 완료되면 닫히거나 파기되어야한다는 것입니다. 또한 다양한 프로토콜 위반이 발생할 때 서버에 의해 닫힙니다.

소비자는 특정 채널의 "메일 박스"의 존재를 나타내는 가상 구조이다. 소비자를 사용하면 브로커에게 특정 큐에서 해당 채널 끝점으로 메시지를 푸시하도록 지시합니다.

연결 사실

첫째, 다른 사람들이 올바르게 지적했듯이 연결 은 서버에 대한 실제 TCP 연결을 나타내는 객체입니다. 연결은 AMQP의 프로토콜 수준에서 지정되며 브로커와의 모든 통신은 하나 이상의 연결을 통해 이루어집니다.

  • 실제 TCP 연결이므로 IP 주소와 포트 번호가 있습니다.
  • 프로토콜 매개 변수는 연결 설정 ( 핸드 셰이크 라고 알려진 프로세스)의 일부로 클라이언트별로 협상됩니다 .
  • 오래 지속 되도록 설계되었습니다 . 연결 클로저가 프로토콜 디자인의 일부인 경우는 거의 없습니다.
  • OSI 관점에서 보면 아마도 레이어 6 주위에있을 것입니다
  • TCP에는이 작업을 수행하기위한 내용이 포함되어 있지 않으므로 연결 상태를 모니터링하도록 하트 비트를 설정할 수 있습니다.
  • 전용 스레드가 기본 TCP 소켓에 대한 읽기 및 쓰기를 관리하도록하는 것이 가장 좋습니다. 전부는 아니지만 대부분 RabbitMQ 클라이언트가이를 수행합니다. 이와 관련하여 일반적으로 스레드 안전합니다.
  • 상대적으로 말하면, 연결은 핸드 셰이크로 인해 "비용이 많이 들지만"실제로는 중요하지 않습니다. 대부분의 프로세스에는 실제로 하나의 연결 개체 만 필요합니다. 그러나 단일 스레드 / 소켓이 제공 할 수있는 것보다 더 많은 처리량이 필요한 경우 (현재 컴퓨팅 기술과 달리) 풀에서 연결을 유지할 수 있습니다.

채널 정보

채널 RabbitMQ 브로커와 통신 할 응용 프로그램의 각 부분에 대한 열 응용 프로그램 세션입니다. 단일 연결을 통해 작동 하며 브로커와의 세션 을 나타냅니다 .

  • 응용 프로그램 논리의 논리적 부분을 나타내므로 각 채널은 일반적으로 자체 스레드에 있습니다.
  • 일반적으로 앱에서 연 모든 채널은 단일 연결을 공유합니다 (연결 위에서 작동하는 간단한 세션입니다). 연결은 스레드로부터 안전하므로 괜찮습니다.
  • 대부분의 AMQP 작업은 채널을 통해 이루어집니다.
  • OSI 레이어 관점에서 채널은 아마도 레이어 7 주위에있을 것입니다 .
  • 채널은 일시적으로 설계되었습니다 . AMQP 설계의 일부는 일반적으로 오류에 대한 응답으로 채널이 닫히는 것입니다 (예 : 기존 대기열을 삭제하기 전에 다른 매개 변수로 대기열을 다시 선언).
  • 일시적이기 때문에 앱에서 채널을 풀링해서는 안됩니다.
  • 서버는 정수를 사용하여 채널을 식별합니다. 연결을 관리하는 스레드가 특정 채널에 대한 패킷을 수신하면이 번호를 사용하여 브로커에게 패킷이 속하는 채널 / 세션을 알려줍니다.
  • 채널은 스레드간에 공유하는 것이 의미가 없으므로 일반적으로 스레드 안전하지 않습니다. 브로커를 사용해야하는 다른 스레드가있는 경우 새 채널이 필요합니다.

소비자 사실

소비자는 AMQP 프로토콜에 의해 정의 된 객체입니다. 채널이나 연결이 아니며 특정 응용 프로그램이 메시지를 삭제하기 위해 일종의 "사서함"으로 사용하는 것입니다.

  • "소비자 생성"은 연결을 통해 채널 을 사용하여 브로커에게 메시지가 해당 채널을 통해 푸시되도록 알리는 것을 의미합니다. 이에 대한 응답으로 브로커는 귀하가 채널에 소비자 가 있음을 등록하고 귀하 에게 메시지를 보내기 시작합니다.
  • 연결을 통해 푸시 된 각 메시지는 채널 번호소비자 번호를 모두 참조합니다 . 이러한 방식으로 연결 관리 스레드 (이 경우 Java API 내)는 메시지로 수행 할 작업을 알고 있습니다. 그런 다음 채널 처리 스레드는 메시지와 함께 수행 할 작업도 알고 있습니다.
  • 소비자 구현은 말 그대로 응용 프로그램마다 다르기 때문에 가장 다양한 변형이 있습니다. 구현에서 메시지가 소비자를 통해 도착할 때마다 작업을 시작하기로 결정했습니다. 따라서 연결을 관리하는 스레드, 채널을 관리하는 스레드 (및 확장으로 소비자) 및 소비자를 통해 전달 된 각 메시지에 대한 하나 이상의 작업 스레드가있었습니다.
  • 닫는 연결하는 연결에 모든 채널을 닫습니다. 닫는 채널은 채널에서 모든 소비자를 닫습니다. 채널을 닫지 않고 소비자 를 취소 할 수도 있습니다 . 세 가지 중 하나를 수행하는 것이 합리적 일 때 다양한 경우가 있습니다.
  • 일반적으로 AMQP 클라이언트에서 소비자를 구현하면 다른 스레드 또는 코드 활동 (게시 포함)과의 충돌을 피하기 위해 하나의 전용 채널을 소비자에게 할당합니다.

소비자 스레드 풀의 의미와 관련하여 Java 클라이언트가 클라이언트에서 프로그래밍 한 것과 비슷한 작업을 수행하고 있다고 생각합니다 (광산은 .Net 클라이언트를 기반으로했지만 크게 수정되었습니다).


1
"채널을 풀링해서는 안됩니다", 이것이 제가 찾는 것입니다
ospider

"이 채널은 일시적이므로 앱에서 채널을 풀링해서는 안됩니다." -이 결론에 어떻게 도달했는지 명확히 할 수 있습니까? 문서는 "스레드 당 하나의 채널"구현이 너무 많은 리소스를 사용하는 경우 채널 풀링을 권장합니다. rabbitmq.com/channels.html#resource-usage
ymas

@ymas-당신이 언급하는 문서는 추측 적이며, 제 생각에는 잘못된 지침입니다. 소스 코드와 프로토콜 사양을 읽고 있습니다. 채널은 풀링되지 않아야합니다. 또한 스레드 당 하나의 채널이 동일한 원칙에 따라 안내됩니다. 서버에 리소스가 제한되어있는 열린 채널이 너무 많으면 아키텍처를 재평가해야합니다 (예 : 고 가용성 구성표로 전환 및 / 또는 동시성 감소).
마이어

21

채널이 하나 인 AMQP 모델의 모든 측면을 설명하는이 기사를 찾았습니다. 내 이해를 반올림하는 데 매우 도움이된다는 것을 알았습니다.

https://www.rabbitmq.com/tutorials/amqp-concepts.html

일부 응용 프로그램은 AMQP 브로커에 여러 연결이 필요합니다. 그러나 많은 TCP 연결을 동시에 열어두면 시스템 리소스가 소비되고 방화벽을 구성하기가 더 어려워 지므로 바람직하지 않습니다. AMQP 0-9-1 연결은 "단일 TCP 연결을 공유하는 경량 연결"로 생각할 수있는 채널과 함께 다중화됩니다.

처리에 여러 스레드 / 프로세스를 사용하는 응용 프로그램의 경우 스레드 / 프로세스 당 새 채널을 열고 채널간에 공유하지 않는 것이 매우 일반적입니다.

특정 채널의 통신은 다른 채널의 통신과 완전히 분리되어 있으므로 모든 AMQP 방법에는 클라이언트가 해당 채널이 어떤 채널인지 파악하기 위해 사용하는 채널 번호도 포함되어 있습니다 (따라서 어떤 이벤트 핸들러를 호출해야하는지). .


4

TCP 연결이 여러 채널을 가질 수있는 것과 같은 관계가 있습니다 .

채널 : 연결 내부의 가상 연결입니다. 대기열에서 메시지를 게시하거나 사용할 때 모든 채널을 통해 수행됩니다 . 연결 : 응용 프로그램과 RabbitMQ 브로커 간의 TCP 연결입니다.

멀티 스레딩 아키텍처에서는 스레드 당 별도의 연결이 필요할 수 있습니다. 이로 인해 TCP 연결이 제대로 활용되지 않을 수 있으며 운영 체제에 오버 헤드를 추가하여 네트워크 사용량이 많은 시간 동안 필요한 TCP 연결 수를 설정합니다. 시스템 성능이 크게 저하 될 수 있습니다. 이것은 채널이 편리한 곳이며 TCP 연결 내에 가상 연결을 만듭니다. 그것은 곧바로 OS의 오버 헤드를 줄이고, 더욱 빠르고 안정적이며 동시에 비동기 작업을 수행 할 수있게합니다. 여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.