示例代码

  1. package main
  2.  
  3. import (
  4. "net"
  5. "os"
  6. "github.com/gpmgo/gopm/modules/goconfig"
  7. "github.com/go-stomp/stomp"
  8. "time"
  9. "strconv"
  10. "log"
  11. "strings"
  12. )
  13.  
  14. // 限制goroutine数量
  15. var limitChan = make(chan bool, ) // Todo 从配置文件中读取
  16.  
  17. // 限制同时处理消息数量
  18. var msgChan = make(chan string, ) // Todo 从配置文件中读取
  19. var activeMqLimitedChan = make(chan bool, )
  20. var activeMq *stomp.Conn
  21. var activeQueue string
  22. var host string
  23. var port string
  24. var connectTimes =
  25. var udpAddress = "0.0.0.0" // Todo 从配置文件中读取
  26. var udpPort = "" // Todo 从配置文件中读取
  27. var logFilePath = "/var/log/syslog_server/"
  28. var configFilePath = "./config.ini"
  29. // UDP goroutine 实现并发读取UDP数据
  30. func udpProcess(conn *net.UDPConn) {
  31. defer func() {
  32. if e := recover(); e != nil {
  33. // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
  34. logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
  35. logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
  36. defer logFile.Close()
  37. if err != nil {
  38. log.Fatalln("open log file error: ", err.Error())
  39. }
  40. logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
  41.  
  42. // 记录错误日志
  43. logger.Println("udpProcess error:", e)
  44. }
  45. // 释放出一个协程
  46. <- limitChan
  47. }()
  48.  
  49. // 最大读取数据大小
  50. data := make([]byte, )
  51. n, _, err := conn.ReadFromUDP(data)
  52. if err != nil {
  53. panic(err)
  54. }
  55.  
  56. // 获取对端的IP地址
  57. // remoteAddr := conn.RemoteAddr()
  58. // msgChan <- remoteAddr.String() + " " + string(data[:n])
  59.  
  60. msgChan <- string(data[:n])
  61.  
  62. }
  63.  
  64. func udpServer(address, port string) {
  65. // @todo 如何防止udpServer 一直Panic导致无限循环重启
  66. defer func() {
  67. if e := recover(); e != nil {
  68. // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
  69. logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
  70. logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
  71. defer logFile.Close()
  72. if err != nil {
  73. log.Fatalln("open log file error: ", err.Error())
  74. }
  75. logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
  76.  
  77. // 记录错误日志
  78. logger.Println("udpServer error:", e)
  79.  
  80. // udpServer启动失败后,间隔10秒后重试
  81. time.Sleep( * time.Second)
  82. udpServer(udpAddress, udpPort)
  83. }
  84. }()
  85.  
  86. udpAddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(address, port))
  87. conn, err := net.ListenUDP("udp", udpAddr)
  88. defer conn.Close()
  89. if err != nil {
  90. panic(err)
  91. }
  92.  
  93. for {
  94. limitChan <- true
  95. go udpProcess(conn)
  96. }
  97. }
  98.  
  99. // 读取ActiveMQ配置信息
  100. func getConfiguration(){
  101. defer func() {
  102. if e := recover(); e != nil {
  103. // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
  104. logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
  105. logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
  106. defer logFile.Close()
  107. if err != nil {
  108. log.Fatalln("open log file error: ", err.Error(), ", programing exit.")
  109. os.Exit()
  110. }
  111. logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
  112.  
  113. // 记录错误日志
  114. logger.Println("Get Configuration error:", e)
  115. }
  116. }()
  117.  
  118. configFile, err := goconfig.LoadConfigFile(configFilePath)
  119. if err != nil {
  120. panic(err)
  121. }
  122.  
  123. host, err = configFile.GetValue("active_mq", "host")
  124. if err != nil {
  125. // 如果没有配置主机,则使用本地主机
  126. host = "127.0.0.1"
  127. }
  128. port, err = configFile.GetValue("active_mq", "port")
  129. if err != nil {
  130. // 如果没配置端口,则使用默认端口
  131. port = ""
  132. }
  133.  
  134. activeQueue, err = configFile.GetValue("active_mq", "queue")
  135. if err != nil {
  136. // 如果没配置端口,则使用默认队列名
  137. activeQueue = "syslog.queue"
  138. }
  139. }
  140.  
  141. // 使用IP和端口连接到ActiveMQ服务器, 返回ActiveMQ连接对象
  142. func connActiveMq(){
  143. // @todo 如何防止无限循环
  144. defer func() {
  145. if e := recover(); e != nil {
  146. // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
  147. logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
  148. logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
  149. defer logFile.Close()
  150. if err != nil {
  151. log.Fatalln("open log file error: ", err.Error())
  152. }
  153. logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
  154.  
  155. // 记录错误日志
  156. logger.Println("connActiveMq error:", e)
  157.  
  158. // ActiveMQ服务器连接失败后,间隔3秒后重试
  159. time.Sleep( * time.Second)
  160. activeMq = nil
  161. connActiveMq()
  162. }
  163. }()
  164.  
  165. // @todo 实现断开重连
  166. if activeMq == nil {
  167. var err error
  168. activeMq, err = stomp.Dial("tcp", net.JoinHostPort(host, port))
  169. if err != nil {
  170. connectTimes ++
  171. if connectTimes >= {
  172. time.Sleep( * time.Second)
  173. }else if connectTimes >= {
  174. time.Sleep( * time.Second)
  175. }else {
  176. time.Sleep( * time.Second)
  177. }
  178. panic(err.Error() + ", 重新连接ActiveMQ, 已重试次数: " + strconv.Itoa(connectTimes))
  179.  
  180. }else {
  181. connectTimes =
  182. }
  183. }
  184. }
  185.  
  186. func activeMqProducer(c chan string){
  187. // @todo 如何防止activeMqProducer 退出
  188. defer func() {
  189. if e := recover(); e != nil {
  190. // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
  191. logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
  192. logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
  193. defer logFile.Close()
  194. if err != nil {
  195. log.Fatalln("open log file error: ", err.Error())
  196. }
  197. logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
  198.  
  199. // 记录错误日志
  200. logger.Println("activeMqProducer error:", e)
  201.  
  202. // 重试
  203. go activeMqProducer(msgChan)
  204. }
  205. }()
  206. for{
  207. activeMqLimitedChan <- true // 限制开启协程数量
  208. contentMsg := <-c
  209. go func() {
  210. defer func() {
  211. if e := recover(); e != nil {
  212. err := os.MkdirAll(logFilePath, )
  213. log.Fatalln("create log dirctory error: ", err.Error())
  214. // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
  215. logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
  216. logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
  217. defer logFile.Close()
  218. if err != nil {
  219. log.Fatalln("open log file error: ", err.Error())
  220. }
  221. logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
  222.  
  223. // 记录错误日志
  224. logger.Println("activeMqProducer error:", e)
  225. }
  226. // 释放出一个协程
  227. <- activeMqLimitedChan
  228. }()
  229.  
  230. err := activeMq.Send(activeQueue, "text/plain", []byte(contentMsg))
  231. if err != nil {
  232. if err.Error() == "connection already closed"{
  233. activeMq = nil
  234. connActiveMq()
  235. activeMq.Send(activeQueue, "text/plain", []byte(contentMsg))
  236. }
  237. panic(err)
  238. }
  239. }()
  240.  
  241. }
  242.  
  243. }
  244.  
  245. func init(){
  246. // 初始化 ActiveMQ 配置
  247. getConfiguration()
  248.  
  249. // 连接到 ActiveMQ 服务器
  250. connActiveMq()
  251.  
  252. // 启动一个协程将Syslog消息放入ActiveMQ队列中
  253. go activeMqProducer(msgChan)
  254.  
  255. }
  256.  
  257. func main() {
  258. defer activeMq.Disconnect()
  259. udpServer(udpAddress, udpPort)
  260. }

Golang 实现UDPServer并发送消息到ActiveMQ的更多相关文章

  1. java 消息机制 ActiveMQ入门实例

    1.下载ActiveMQ 去官方网站下载:http://activemq.apache.org/ 我下载的时候是 ActiveMQ 5.14.0 Release版 2.运行ActiveMQ 解压缩ap ...

  2. Java消息机制 ActiveMQ入门实例

    转载自:http://www.cnblogs.com/wyh3721/p/5917316.html 1.下载ActiveMQ 去官方网站下载:http://activemq.apache.org/  ...

  3. java之消息队列ActiveMQ实践

    原创论文:https://www.cnblogs.com/goujh/p/8510239.html 消息队列的应用场景: 消息队列应用场景 异步处理,应用解耦,流量削锋和消息通讯四个场景 异步处理: ...

  4. Golang之发送消息至kafka

    windows下安装zookeeper 1.安装JAVA-JDK,从oracle下载最新的SDK安装(我用的是1.8的) 2.安装zookeeper3.3.6,下载地址:http://apache.f ...

  5. ActiveMQ producer不断发送消息,会导致broker内存耗尽吗?

    http://activemq.apache.org/my-producer-blocks.html 回答了这个问题: ActiveMQ 5.x 支持Message Cursors,它默认把消息从内存 ...

  6. ActiveMQ producer同步/异步发送消息

    http://activemq.apache.org/async-sends.html producer发送消息有同步和异步两种模式,可以通过代码配置: ((ActiveMQConnection)co ...

  7. php 事务处理,ActiveMQ的发送消息,与处理消息

    可以通过链式发送->处理->发送...的方式处理类似事务型业务逻辑 比如 发送一个注册消息,消息队列处理完注册以后,紧接着发送一个新手优惠券赠送,赠送完再发一个其它后续逻辑处理的消息等待后 ...

  8. 【Java Web开发学习】Spring消息-ActiveMQ发送消息

    ActiveMQ发送消息 转载:http://www.cnblogs.com/yangchongxing/p/9042401.html Java消息服务(Java Message Service, J ...

  9. activeMq发送消息流程

    1,发送消息入口 Message message = messageBean.getMessageCreator().createMessage(session); producer.send(mes ...

随机推荐

  1. 项目Beta冲刺(团队3/7)

    项目Beta冲刺(团队) --3/7 作业要求: 项目Beta冲刺(团队) 1.团队信息 团队名 :男上加男 成员信息 : 队员学号 队员姓名 个人博客地址 备注 221600427 Alicesft ...

  2. JAVA接口与类的区别

    抽象类:一个类中有抽象方法,这个类就变成了抽象类.抽象类中class的前面必须有abstract修饰符.抽象类中可以有普通方法,也可以有抽象方法,而抽象方法的个数可以是0个,也可以是多个.子类继承父类 ...

  3. The Role of View Controllers

    https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/index.html# ...

  4. 构造方法(_ _construct) 和析构方法(__destruct)

    构造方法,是一个特殊的方法: 1,名字是固定的:_ _construct: 2,该方法通常都不要我们自己调用,而是在new一个对象的时候会自动调用. 3,该方法主要的目的是为了在new一个对象的时候, ...

  5. select函数及fd_set介绍

    1. select函数 1. 用途 在编程的过程中,经常会遇到许多阻塞的函数,好像read和网络编程时使用的recv, recvfrom函数都是阻塞的函数,当函数不能成功执行的时候,程序就会一直阻塞在 ...

  6. codeblocks异常退出

    ExceptionAn exception has been raised! The application encountered an error atC:\CB1312\src\sdk\conf ...

  7. C函数之index、strtoul

    index函数 函数定义: #include<strings.h> char *index(const char *s, int c); 函数说明: 找出参数s字符串中第一个出现参数c的地 ...

  8. 【11NOIP提高组】选择客栈(信息学奥赛一本通 1546)(洛谷 1311)

    题目描述 丽江河边有nn家很有特色的客栈,客栈按照其位置顺序从 11到nn编号.每家客栈都按照某一种色调进行装饰(总共 kk 种,用整数 00 ~k-1k−1 表示),且每家客栈都设有一家咖啡店,每家 ...

  9. 【AtCoder】 ARC 101

    link 搬来了曾经的题解 C-Candles 题意:数轴上有一些点,从原点开始移动到达这些点中的任意\(K\)个所需要的最短总路程 \(K\)个点必然是一个区间,枚举最左边的就行了 #include ...

  10. cgdsR 下载TCGA数据

    TCGA 的数据可以在5个组织机构获取,它们都提供了类似的接口来供用户下载数据. cgdsR 包是cBioPortal 提供的R包 http://www.cbioportal.org/rmatlab ...