You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

server.go 3.7 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. package mq
  2. import (
  3. "fmt"
  4. "github.com/streadway/amqp"
  5. )
  6. type ReceiveMessageError struct {
  7. err error
  8. }
  9. func (err ReceiveMessageError) Error() string {
  10. return fmt.Sprintf("receive message error: %s", err.err.Error())
  11. }
  12. func NewReceiveMessageError(err error) ReceiveMessageError {
  13. return ReceiveMessageError{
  14. err: err,
  15. }
  16. }
  17. type DeserializeError struct {
  18. err error
  19. }
  20. func (err DeserializeError) Error() string {
  21. return fmt.Sprintf("deserialize error: %s", err.err.Error())
  22. }
  23. func NewDeserializeError(err error) DeserializeError {
  24. return DeserializeError{
  25. err: err,
  26. }
  27. }
  28. type DispatchError struct {
  29. err error
  30. }
  31. func (err DispatchError) Error() string {
  32. return fmt.Sprintf("dispatch error: %s", err.err.Error())
  33. }
  34. func NewDispatchError(err error) DispatchError {
  35. return DispatchError{
  36. err: err,
  37. }
  38. }
  39. type ReplyError struct {
  40. err error
  41. }
  42. func (err ReplyError) Error() string {
  43. return fmt.Sprintf("replay to client : %s", err.err.Error())
  44. }
  45. func NewReplyError(err error) ReplyError {
  46. return ReplyError{
  47. err: err,
  48. }
  49. }
  50. // 处理消息。会将第一个返回值作为响应回复给客户端,如果为nil,则不回复。
  51. type MessageHandlerFn func(msg *Message) (*Message, error)
  52. type RabbitMQServer struct {
  53. queueName string
  54. connection *amqp.Connection
  55. channel *amqp.Channel
  56. closed chan any
  57. OnMessage MessageHandlerFn
  58. OnError func(err error)
  59. }
  60. func NewRabbitMQServer(url string, queueName string, onMessage MessageHandlerFn) (*RabbitMQServer, error) {
  61. connection, err := amqp.Dial(url)
  62. if err != nil {
  63. return nil, fmt.Errorf("connecting to %s: %w", url, err)
  64. }
  65. channel, err := connection.Channel()
  66. if err != nil {
  67. connection.Close()
  68. return nil, fmt.Errorf("openning channel on connection: %w", err)
  69. }
  70. srv := &RabbitMQServer{
  71. connection: connection,
  72. channel: channel,
  73. queueName: queueName,
  74. closed: make(chan any),
  75. OnMessage: onMessage,
  76. }
  77. return srv, nil
  78. }
  79. func (s *RabbitMQServer) Serve() error {
  80. _, err := s.channel.QueueDeclare(
  81. s.queueName,
  82. false,
  83. true,
  84. false,
  85. false,
  86. nil,
  87. )
  88. if err != nil {
  89. return fmt.Errorf("declare queue failed, err: %w", err)
  90. }
  91. channel, err := s.channel.Consume(
  92. s.queueName,
  93. "",
  94. true,
  95. false,
  96. true,
  97. false,
  98. nil,
  99. )
  100. if err != nil {
  101. return fmt.Errorf("open consume channel failed, err: %w", err)
  102. }
  103. for {
  104. select {
  105. case rawReq, ok := <-channel:
  106. if !ok {
  107. if s.OnError != nil {
  108. s.OnError(NewReceiveMessageError(fmt.Errorf("channel is closed")))
  109. }
  110. return NewReceiveMessageError(fmt.Errorf("channel is closed"))
  111. }
  112. reqMsg, err := Deserialize(rawReq.Body)
  113. if err != nil {
  114. if s.OnError != nil {
  115. s.OnError(NewDeserializeError(err))
  116. }
  117. break
  118. }
  119. reply, err := s.OnMessage(reqMsg)
  120. if err != nil {
  121. if s.OnError != nil {
  122. s.OnError(NewDispatchError(err))
  123. }
  124. continue
  125. }
  126. if reply != nil {
  127. reply.SetRequestID(reqMsg.GetRequestID())
  128. err := s.replyClientMessage(*reply, &rawReq)
  129. if err != nil {
  130. if s.OnError != nil {
  131. s.OnError(NewReplyError(err))
  132. }
  133. }
  134. }
  135. case <-s.closed:
  136. return nil
  137. }
  138. }
  139. }
  140. func (s *RabbitMQServer) Close() {
  141. close(s.closed)
  142. }
  143. // replyClientMessage 回复客户端的消息,需要用到客户端发来的消息中的字段来判断回到哪个队列
  144. func (s *RabbitMQServer) replyClientMessage(reply Message, reqMsg *amqp.Delivery) error {
  145. msgData, err := Serialize(reply)
  146. if err != nil {
  147. return fmt.Errorf("serialize message failed: %w", err)
  148. }
  149. return s.channel.Publish(
  150. "",
  151. reqMsg.ReplyTo,
  152. false,
  153. false,
  154. amqp.Publishing{
  155. ContentType: "text/plain",
  156. Body: msgData,
  157. Expiration: "30000", // 响应消息的超时时间默认30秒
  158. },
  159. )
  160. }

公共库