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 ...
随机推荐
- 201671010446姚良实验十四团队项目评审&课程总结
实验十四 团队项目评审&课程学习总结 项目 内容 这个作业属于哪个课程 http://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cn ...
- python应用-已知三角形的边长求他的面积和周长
""" 已知三角形的边长求他的面积和周长 Author:罗万财 Date:2017-3-3 """ import math a=float( ...
- js不常用,但很实用的功能
=============== 通知: 博主已迁至<掘金>码字,博客园可能以后不再更新,掘金地址:https://juejin.im/post/5a1a6a6551882534af25a8 ...
- 记一次PATH环境变量设置不生效的问题
问题:卸载原有版本jdk后,如下图在/etc/profile中配置新的环境变量且source /etc/profile 生效配置后,JAVA_HOME值都正确,但PATH变量值还是不对 echo $P ...
- 使用kubeadm 安装 kubernetes 1.15.1
简介: Kubernetes作为Google开源的容器运行平台,受到了大家的热捧.搭建一套完整的kubernetes平台,也成为试用这套平台必须迈过的坎儿.kubernetes1.5版本以及之前,安装 ...
- Wooden Signs Gym - 101128E (DP)
Problem E: Wooden Signs \[ Time Limit: 1 s \quad Memory Limit: 256 MiB \] 题意 给出一个\(n\),接下来\(n+1\)个数, ...
- LeetCode 981. Time Based Key-Value Store
原题链接在这里:https://leetcode.com/problems/time-based-key-value-store/ 题目: Create a timebased key-value s ...
- Edge Beta 进入无痕模式 快捷方式
“浏览器路径” -InPrivate 在快捷方式的路径后加 -InPrivate 就可以了
- Pandas模块 -- 实操练习
如果对序列进行数学函数的运算,首选numpy模块: 如果对序列做统计运算,首选序列的“方法”,因为序列的“方法”更加丰富,如计算序列的偏度.峰度等,而Numpy模块是没有这样的函数. 手工构造数据框D ...
- Spark 部署即提交模式意义解析
Spark 的官方从 Cluster Mode Overview 中,官方向我们介绍了 cluster 模式的部署方式. Spark 作为独立进程在集群上运行,他们通过 SparkContext 进行 ...