[C#/COMMON/RABBITMQ] Remote Procedure Call 사용하기
■ Remote Procedure Call을 사용하는 방법을 보여준다. [TestProducer 프로젝트] ▶ Program.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
using System; using System.Text; using RabbitMQ.Client; using RabbitMQ.Client.Events; namespace TestProducer { /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> /// <param name="argumentArray">인자 배열</param> private static void Main(string[] argumentArray) { ConnectionFactory factory = new ConnectionFactory() { HostName = "localhost" }; using(IConnection connection = factory.CreateConnection()) { using(IModel model = connection.CreateModel()) { model.QueueDeclare ( queue : "rpc_queue", durable : false, exclusive : false, autoDelete : false, arguments : null ); model.BasicQos(0, 1, false); EventingBasicConsumer consumer = new EventingBasicConsumer(model); model.BasicConsume ( queue : "rpc_queue", autoAck : false, consumer : consumer ); WriteLog("RPC 요청을 대기하고 있습니다."); consumer.Received += (sender, e) => { string response = null; byte[] requestArray = e.Body; IBasicProperties requestBasicProperties = e.BasicProperties; IBasicProperties replyBasicProperties = model.CreateBasicProperties(); replyBasicProperties.CorrelationId = requestBasicProperties.CorrelationId; try { string requestMessage = Encoding.UTF8.GetString(requestArray); int value = int.Parse(requestMessage); WriteLog("{0}의 피보나치 수열 계산을 시작합니다.", requestMessage); int result = GetFibonacciSequence(value); response = result.ToString(); } catch(Exception exception) { WriteLog("예외가 발생했습니다 :\n{0}", exception.Message); response = ""; } finally { byte[] responseByteArray = Encoding.UTF8.GetBytes(response); model.BasicPublish ( exchange : "", routingKey : requestBasicProperties.ReplyTo, basicProperties : replyBasicProperties, body : responseByteArray ); model.BasicAck ( deliveryTag : e.DeliveryTag, multiple : false ); } }; Console.WriteLine("프로그램을 종료하려면 아무 키나 눌러 주시기 바랍니다."); Console.ReadKey(true); } } } #endregion #region 로그 작성하기 - WriteLog(format, parameterArray) /// <summary> /// 로그 작성하기 /// </summary> /// <param name="format">포맷 문자열</param> /// <param name="parameterArray">매개 변수 배열</param> private static void WriteLog(string format, params object[] parameterArray) { string message; if(parameterArray.Length == 0) { message = format; } else { message = string.Format(format, parameterArray); } string log = string.Format("[{0}] {1}", DateTime.Now.ToString("HH:mm:ss"), message); Console.WriteLine(log); } #endregion #region 피보나치 수열 구하기 - GetFibonacciSequence(sourceValue) /// <summary> /// 피보나치 수열 구하기 /// </summary> /// <param name="sourceValue">소스 값</param> /// <returns>피보나치 수열</returns> private static int GetFibonacciSequence(int sourceValue) { if(sourceValue == 0 || sourceValue == 1) { return sourceValue; } return GetFibonacciSequence(sourceValue - 1) + GetFibonacciSequence(sourceValue - 2); } #endregion } } |
[TestConsumer 프로젝트] ▶ RPCClient.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
using System; using System.Collections.Concurrent; using System.Text; using RabbitMQ.Client; using RabbitMQ.Client.Events; namespace TestConsumer { /// <summary> /// RPC 클라이언트 /// </summary> public class RPCClient { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 연결 /// </summary> private readonly IConnection connection; /// <summary> /// 모델 /// </summary> private readonly IModel model; /// <summary> /// 응답 큐 명칭 /// </summary> private readonly string replyQueueName; /// <summary> /// 이벤트 기본 소비자 /// </summary> private readonly EventingBasicConsumer eventingBasicConsumer; /// <summary> /// 기본 속성 /// </summary> private readonly IBasicProperties basicProperties; /// <summary> /// 차단 컬렉션 /// </summary> private readonly BlockingCollection<string> blockingCollection = new BlockingCollection<string>(); #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - RPCClient() /// <summary> /// 생성자 /// </summary> public RPCClient() { ConnectionFactory factory = new ConnectionFactory() { HostName = "localhost" }; this.connection = factory.CreateConnection(); this.model = this.connection.CreateModel(); this.replyQueueName = this.model.QueueDeclare().QueueName; this.eventingBasicConsumer = new EventingBasicConsumer(this.model); this.basicProperties = this.model.CreateBasicProperties(); string correlationID = Guid.NewGuid().ToString(); this.basicProperties.CorrelationId = correlationID; this.basicProperties.ReplyTo = this.replyQueueName; this.eventingBasicConsumer.Received += (sender, e) => { byte[] responseMessageArray = e.Body; string responseMessage = Encoding.UTF8.GetString(responseMessageArray); if(e.BasicProperties.CorrelationId == correlationID) { blockingCollection.Add(responseMessage); } }; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 피보나치 수열 구하기 - GetFibonacciSequence(value) /// <summary> /// 피보나치 수열 구하기 /// </summary> /// <param name="value">값</param> /// <returns>피보나치 수열</returns> public long GetFibonacciSequence(int value) { string message = value.ToString(); byte[] messageByteArray = Encoding.UTF8.GetBytes(message); this.model.BasicPublish ( exchange : "", routingKey : "rpc_queue", basicProperties : this.basicProperties, body : messageByteArray ); this.model.BasicConsume ( consumer : eventingBasicConsumer, queue : this.replyQueueName, autoAck : true ); string responseMessage = blockingCollection.Take(); return Convert.ToInt64(responseMessage); } #endregion #region 닫기 - Close() /// <summary> /// 닫기 /// </summary> public void Close() { this.connection.Close(); } #endregion } } |
▶ Program.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
using System; namespace TestConsumer { /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main(argumentArray) /// <summary> /// 프로그램 시작하기 /// </summary> /// <param name="argumentArray">인자 배열</param> private static void Main(string[] argumentArray) { RPCClient client = new RPCClient(); WriteLog("30의 피보나치 수열 요청중..."); long result = client.GetFibonacciSequence(30); WriteLog("결과 : {0}", result); client.Close(); } #endregion #region 로그 작성하기 - WriteLog(format, parameterArray) /// <summary> /// 로그 작성하기 /// </summary> /// <param name="format">포맷 문자열</param> /// <param name="parameterArray">매개 변수 배열</param> private static void WriteLog(string format, params object[] parameterArray) { string message; if(parameterArray.Length == 0) { message = format; } else { message = string.Format(format, parameterArray); } string log = string.Format("[{0}] {1}", DateTime.Now.ToString("HH:mm:ss"), message); Console.WriteLine(log); } #endregion } } |
TestSolution.zip