Golang 实现UDPServer并发送消息到ActiveMQ
示例代码
- package main
- import (
- "net"
- "os"
- "github.com/gpmgo/gopm/modules/goconfig"
- "github.com/go-stomp/stomp"
- "time"
- "strconv"
- "log"
- "strings"
- )
- // 限制goroutine数量
- var limitChan = make(chan bool, ) // Todo 从配置文件中读取
- // 限制同时处理消息数量
- var msgChan = make(chan string, ) // Todo 从配置文件中读取
- var activeMqLimitedChan = make(chan bool, )
- var activeMq *stomp.Conn
- var activeQueue string
- var host string
- var port string
- var connectTimes =
- var udpAddress = "0.0.0.0" // Todo 从配置文件中读取
- var udpPort = "" // Todo 从配置文件中读取
- var logFilePath = "/var/log/syslog_server/"
- var configFilePath = "./config.ini"
- // UDP goroutine 实现并发读取UDP数据
- func udpProcess(conn *net.UDPConn) {
- defer func() {
- if e := recover(); e != nil {
- // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
- logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
- logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
- defer logFile.Close()
- if err != nil {
- log.Fatalln("open log file error: ", err.Error())
- }
- logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
- // 记录错误日志
- logger.Println("udpProcess error:", e)
- }
- // 释放出一个协程
- <- limitChan
- }()
- // 最大读取数据大小
- data := make([]byte, )
- n, _, err := conn.ReadFromUDP(data)
- if err != nil {
- panic(err)
- }
- // 获取对端的IP地址
- // remoteAddr := conn.RemoteAddr()
- // msgChan <- remoteAddr.String() + " " + string(data[:n])
- msgChan <- string(data[:n])
- }
- func udpServer(address, port string) {
- // @todo 如何防止udpServer 一直Panic导致无限循环重启
- defer func() {
- if e := recover(); e != nil {
- // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
- logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
- logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
- defer logFile.Close()
- if err != nil {
- log.Fatalln("open log file error: ", err.Error())
- }
- logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
- // 记录错误日志
- logger.Println("udpServer error:", e)
- // udpServer启动失败后,间隔10秒后重试
- time.Sleep( * time.Second)
- udpServer(udpAddress, udpPort)
- }
- }()
- udpAddr, err := net.ResolveUDPAddr("udp", net.JoinHostPort(address, port))
- conn, err := net.ListenUDP("udp", udpAddr)
- defer conn.Close()
- if err != nil {
- panic(err)
- }
- for {
- limitChan <- true
- go udpProcess(conn)
- }
- }
- // 读取ActiveMQ配置信息
- func getConfiguration(){
- defer func() {
- if e := recover(); e != nil {
- // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
- logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
- logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
- defer logFile.Close()
- if err != nil {
- log.Fatalln("open log file error: ", err.Error(), ", programing exit.")
- os.Exit()
- }
- logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
- // 记录错误日志
- logger.Println("Get Configuration error:", e)
- }
- }()
- configFile, err := goconfig.LoadConfigFile(configFilePath)
- if err != nil {
- panic(err)
- }
- host, err = configFile.GetValue("active_mq", "host")
- if err != nil {
- // 如果没有配置主机,则使用本地主机
- host = "127.0.0.1"
- }
- port, err = configFile.GetValue("active_mq", "port")
- if err != nil {
- // 如果没配置端口,则使用默认端口
- port = ""
- }
- activeQueue, err = configFile.GetValue("active_mq", "queue")
- if err != nil {
- // 如果没配置端口,则使用默认队列名
- activeQueue = "syslog.queue"
- }
- }
- // 使用IP和端口连接到ActiveMQ服务器, 返回ActiveMQ连接对象
- func connActiveMq(){
- // @todo 如何防止无限循环
- defer func() {
- if e := recover(); e != nil {
- // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
- logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
- logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
- defer logFile.Close()
- if err != nil {
- log.Fatalln("open log file error: ", err.Error())
- }
- logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
- // 记录错误日志
- logger.Println("connActiveMq error:", e)
- // ActiveMQ服务器连接失败后,间隔3秒后重试
- time.Sleep( * time.Second)
- activeMq = nil
- connActiveMq()
- }
- }()
- // @todo 实现断开重连
- if activeMq == nil {
- var err error
- activeMq, err = stomp.Dial("tcp", net.JoinHostPort(host, port))
- if err != nil {
- connectTimes ++
- if connectTimes >= {
- time.Sleep( * time.Second)
- }else if connectTimes >= {
- time.Sleep( * time.Second)
- }else {
- time.Sleep( * time.Second)
- }
- panic(err.Error() + ", 重新连接ActiveMQ, 已重试次数: " + strconv.Itoa(connectTimes))
- }else {
- connectTimes =
- }
- }
- }
- func activeMqProducer(c chan string){
- // @todo 如何防止activeMqProducer 退出
- defer func() {
- if e := recover(); e != nil {
- // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
- logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
- logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
- defer logFile.Close()
- if err != nil {
- log.Fatalln("open log file error: ", err.Error())
- }
- logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
- // 记录错误日志
- logger.Println("activeMqProducer error:", e)
- // 重试
- go activeMqProducer(msgChan)
- }
- }()
- for{
- activeMqLimitedChan <- true // 限制开启协程数量
- contentMsg := <-c
- go func() {
- defer func() {
- if e := recover(); e != nil {
- err := os.MkdirAll(logFilePath, )
- log.Fatalln("create log dirctory error: ", err.Error())
- // 初始化日志,每天生成一个日志文件,日志文件名以日志结尾
- logFileName := logFilePath + "server-" + strings.Split(time.Now().String(), " ")[] + ".log"
- logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, ) // 应该判断error,此处简略
- defer logFile.Close()
- if err != nil {
- log.Fatalln("open log file error: ", err.Error())
- }
- logger := log.New(logFile, "[Error] ", log.Ldate|log.Ltime|log.Lshortfile)
- // 记录错误日志
- logger.Println("activeMqProducer error:", e)
- }
- // 释放出一个协程
- <- activeMqLimitedChan
- }()
- err := activeMq.Send(activeQueue, "text/plain", []byte(contentMsg))
- if err != nil {
- if err.Error() == "connection already closed"{
- activeMq = nil
- connActiveMq()
- activeMq.Send(activeQueue, "text/plain", []byte(contentMsg))
- }
- panic(err)
- }
- }()
- }
- }
- func init(){
- // 初始化 ActiveMQ 配置
- getConfiguration()
- // 连接到 ActiveMQ 服务器
- connActiveMq()
- // 启动一个协程将Syslog消息放入ActiveMQ队列中
- go activeMqProducer(msgChan)
- }
- func main() {
- defer activeMq.Disconnect()
- udpServer(udpAddress, udpPort)
- }
Golang 实现UDPServer并发送消息到ActiveMQ的更多相关文章
- java 消息机制 ActiveMQ入门实例
1.下载ActiveMQ 去官方网站下载:http://activemq.apache.org/ 我下载的时候是 ActiveMQ 5.14.0 Release版 2.运行ActiveMQ 解压缩ap ...
- Java消息机制 ActiveMQ入门实例
转载自:http://www.cnblogs.com/wyh3721/p/5917316.html 1.下载ActiveMQ 去官方网站下载:http://activemq.apache.org/ ...
- java之消息队列ActiveMQ实践
原创论文:https://www.cnblogs.com/goujh/p/8510239.html 消息队列的应用场景: 消息队列应用场景 异步处理,应用解耦,流量削锋和消息通讯四个场景 异步处理: ...
- Golang之发送消息至kafka
windows下安装zookeeper 1.安装JAVA-JDK,从oracle下载最新的SDK安装(我用的是1.8的) 2.安装zookeeper3.3.6,下载地址:http://apache.f ...
- ActiveMQ producer不断发送消息,会导致broker内存耗尽吗?
http://activemq.apache.org/my-producer-blocks.html 回答了这个问题: ActiveMQ 5.x 支持Message Cursors,它默认把消息从内存 ...
- ActiveMQ producer同步/异步发送消息
http://activemq.apache.org/async-sends.html producer发送消息有同步和异步两种模式,可以通过代码配置: ((ActiveMQConnection)co ...
- php 事务处理,ActiveMQ的发送消息,与处理消息
可以通过链式发送->处理->发送...的方式处理类似事务型业务逻辑 比如 发送一个注册消息,消息队列处理完注册以后,紧接着发送一个新手优惠券赠送,赠送完再发一个其它后续逻辑处理的消息等待后 ...
- 【Java Web开发学习】Spring消息-ActiveMQ发送消息
ActiveMQ发送消息 转载:http://www.cnblogs.com/yangchongxing/p/9042401.html Java消息服务(Java Message Service, J ...
- activeMq发送消息流程
1,发送消息入口 Message message = messageBean.getMessageCreator().createMessage(session); producer.send(mes ...
随机推荐
- 项目Beta冲刺(团队3/7)
项目Beta冲刺(团队) --3/7 作业要求: 项目Beta冲刺(团队) 1.团队信息 团队名 :男上加男 成员信息 : 队员学号 队员姓名 个人博客地址 备注 221600427 Alicesft ...
- JAVA接口与类的区别
抽象类:一个类中有抽象方法,这个类就变成了抽象类.抽象类中class的前面必须有abstract修饰符.抽象类中可以有普通方法,也可以有抽象方法,而抽象方法的个数可以是0个,也可以是多个.子类继承父类 ...
- The Role of View Controllers
https://developer.apple.com/library/content/featuredarticles/ViewControllerPGforiPhoneOS/index.html# ...
- 构造方法(_ _construct) 和析构方法(__destruct)
构造方法,是一个特殊的方法: 1,名字是固定的:_ _construct: 2,该方法通常都不要我们自己调用,而是在new一个对象的时候会自动调用. 3,该方法主要的目的是为了在new一个对象的时候, ...
- select函数及fd_set介绍
1. select函数 1. 用途 在编程的过程中,经常会遇到许多阻塞的函数,好像read和网络编程时使用的recv, recvfrom函数都是阻塞的函数,当函数不能成功执行的时候,程序就会一直阻塞在 ...
- codeblocks异常退出
ExceptionAn exception has been raised! The application encountered an error atC:\CB1312\src\sdk\conf ...
- C函数之index、strtoul
index函数 函数定义: #include<strings.h> char *index(const char *s, int c); 函数说明: 找出参数s字符串中第一个出现参数c的地 ...
- 【11NOIP提高组】选择客栈(信息学奥赛一本通 1546)(洛谷 1311)
题目描述 丽江河边有nn家很有特色的客栈,客栈按照其位置顺序从 11到nn编号.每家客栈都按照某一种色调进行装饰(总共 kk 种,用整数 00 ~k-1k−1 表示),且每家客栈都设有一家咖啡店,每家 ...
- 【AtCoder】 ARC 101
link 搬来了曾经的题解 C-Candles 题意:数轴上有一些点,从原点开始移动到达这些点中的任意\(K\)个所需要的最短总路程 \(K\)个点必然是一个区间,枚举最左边的就行了 #include ...
- cgdsR 下载TCGA数据
TCGA 的数据可以在5个组织机构获取,它们都提供了类似的接口来供用户下载数据. cgdsR 包是cBioPortal 提供的R包 http://www.cbioportal.org/rmatlab ...