Go项目实战:打造高并发日志采集系统(二)
日志统计系统的整体思路就是监控各个文件夹下的日志,实时获取日志写入内容并写入kafka队列,写入kafka队列可以在高并发时排队,而且达到了逻辑解耦合的目的。然后从kafka队列中读出数据,根据实际需求显示网页上或者控制台等。
前情提要
上一节我们完成了如下目标
1 配置kafka,并启动消息队列。
2 编写代码向kafka录入消息,并且从kafka读取消息。
本节目标
1 写代码从kafka中读取消息,保证kafka消息读写功能无误。
2 借助tailf实现文件监控,并模拟测试事实写文件以及文件备份时功能无误。
3 本系列文章开发语言使用Go
从kafka中读取消息
func main(){
fmt.Println("consumer begin...")
config := sarama.NewConfig()
config.Consumer.Return.Errors = true
wg :=sync.WaitGroup{}
//创建消费者
consumer, err := sarama.NewConsumer([]string{"localhost:9092"},config)
if err != nil {
fmt.Println("consumer create failed, error is ", err.Error())
return
}
defer consumer.Close() //Partitions(topic):该方法返回了该topic的所有分区id
partitionList, err := consumer.Partitions("test")
if err != nil {
fmt.Println("get consumer partitions failed")
fmt.Println("error is ", err.Error())
return
} for partition := range partitionList {
//ConsumePartition方法根据主题,
//分区和给定的偏移量创建创建了相应的分区消费者
//如果该分区消费者已经消费了该信息将会返回error
//OffsetNewest消费最新数据
pc, err := consumer.ConsumePartition("test", int32(partition), sarama.OffsetNewest)
if err != nil {
panic(err)
}
//异步关闭,保证数据落盘
defer pc.AsyncClose()
wg.Add(1)
go func(sarama.PartitionConsumer) {
defer wg.Done()
//Messages()该方法返回一个消费消息类型的只读通道,由代理产生
for msg := range pc.Messages() {
fmt.Printf("%s---Partition:%d, Offset:%d, Key:%s, Value:%s\n",
msg.Topic,msg.Partition, msg.Offset, string(msg.Key), string(msg.Value))
}
}(pc)
}
wg.Wait()
consumer.Close() }
这样我们启动zookeeper和kafka后,分别运行前文实现的向kafka中写入数据的代码,以及现在的从kafka中消费的代码,看到如下效果
实现文件监控
实现文件监控,主要是在文件中有内容写入时,程序可以及时获取写入的内容,类似于Linux命令中的tailf -f 某个文件的功能。
golang 中提供了tail库,我们借助这个库完成指定文件的监控,我的文件组织如下
logdir文件夹下的log.txt记录的是不断增加的日志文件
tailf文件夹下logtailf.go实现log.txt监控功能。
writefile文件夹下writefile.go实现的是向log.txt文件写日志并备份的功能。
func main() {
logrelative := `../logdir/log.txt`
_, filename, _, _ := runtime.Caller(0)
fmt.Println(filename)
datapath := path.Join(path.Dir(filename), logrelative)
fmt.Println(datapath)
tailFile, err := tail.TailFile(datapath, tail.Config{
//文件被移除或被打包,需要重新打开
ReOpen: true,
//实时跟踪
Follow: true,
//如果程序出现异常,保存上次读取的位置,避免重新读取
Location: &tail.SeekInfo{Offset: 0, Whence: 2},
//支持文件不存在
MustExist: false,
Poll: true,
}) if err != nil {
fmt.Println("tail file err:", err)
return
} for true {
msg, ok := <-tailFile.Lines
if !ok {
fmt.Printf("tail file close reopen, filename: %s\n", tailFile.Filename)
time.Sleep(100 * time.Millisecond)
continue
}
//fmt.Println("msg:", msg)
//只打印text
fmt.Println("msg:", msg.Text)
}
}
为了测试监控的功能。我们实现向log.txt中每隔0.1s写入一行”Hello+时间戳”的日志。当写入20条内容后我们将log.txt备份重命名。
然后创建新的log.txt继续写入。
在writefile.go实现一个函数定时写入,并且备份功能
func writeLog(datapath string) {
filew, err := os.OpenFile(datapath, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
if err != nil {
fmt.Println("open file error ", err.Error())
return
} w := bufio.NewWriter(filew)
for i := 0; i < 20; i++ {
timeStr := time.Now().Format("2006-01-02 15:04:05")
fmt.Fprintln(w, "Hello current time is "+timeStr)
time.Sleep(time.Millisecond * 100)
w.Flush()
}
logBak := time.Now().Format("20060102150405") + ".txt"
logBak = path.Join(path.Dir(datapath), logBak)
filew.Close()
err = os.Rename(datapath, logBak)
if err != nil {
fmt.Println("Rename error ", err.Error())
return
}
}
然后我们实现main函数,调用三次writeLog,这样会产生三个备份文件
func main() {
logrelative := `../logdir/log.txt`
_, filename, _, _ := runtime.Caller(0)
fmt.Println(filename)
datapath := path.Join(path.Dir(filename), logrelative)
for i := 0; i < 3; i++ {
writeLog(datapath)
}
}
我们分别启动文件监控和文件写入程序,效果如下
可以看到,当log.txt有内容写入时,logtailf.go实现了动态监控,而且当文件备份时,logtailf.go提示了文件被重命名备份。
最终我们看到产生三个备份文件
总结
目前我们已经完成了kafka消息读写,文件监控,动态写入和备份等功能,接下来我们实现项目的配置化和统筹代码。
源码下载
https://github.com/secondtonone1/golang-
感谢关注我的公众号
Go项目实战:打造高并发日志采集系统(二)的更多相关文章
- Go项目实战:打造高并发日志采集系统(一)
项目结构 本系列文章意在记录如何搭建一个高可用的日志采集系统,实际项目中会有多个日志文件分布在服务器各个文件夹,这些日志记录了不同的功能.随着业务的增多,日志文件也再增多,企业中常常需要实现一个独立的 ...
- Go项目实战:打造高并发日志采集系统(六)
前情回顾 前文我们完成了日志采集系统的日志文件监控,配置文件热更新,协程异常检测和保活机制. 本节目标 本节加入kafka消息队列,kafka前文也介绍过了,可以对消息进行排队,解耦合和流量控制的作用 ...
- Go项目实战:打造高并发日志采集系统(三)
前文中已经完成了文件的监控,kafka信息读写,今天主要完成配置文件的读写以及热更新.并且规划一下系统的整体结构,然后将之前的功能串起来形成一套完整的日志采集系统. 前情提要 上一节我们完成了如下目标 ...
- Go项目实战:打造高并发日志采集系统(四)
前情回顾 前文我们完成了如下目标1 项目架构整体编写2 使框架支持热更新 本节目标 在前文的框架基础上,我们1 将之前实现的日志监控功能整合到框架中.2 一个日志对应一个监控协程,当配置热更新后根据新 ...
- Go项目实战:打造高并发日志采集系统(五)
前情回顾 前文我们完成了如下功能1 根据配置文件启动多个协程监控日志,并启动协程监听配置文件.2 根据配置文件热更新,动态协调日志监控.3 编写测试代码,向文件中不断写入日志并备份日志,验证系统健壮性 ...
- 《实战java高并发程序设计》源码整理及读书笔记
日常啰嗦 不要被标题吓到,虽然书籍是<实战java高并发程序设计>,但是这篇文章不会讲高并发.线程安全.锁啊这些比较恼人的知识点,甚至都不会谈相关的技术,只是写一写本人的一点读书感受,顺便 ...
- 《实战Java高并发程序设计》读书笔记
文章目录 第二章 Java并行程序基础 2.1 线程的基本操作 2.1.1 线程中断 2.1.2 等待(wait)和通知(notify) 2.1.3 等待线程结束(join)和谦让(yield) 2. ...
- 【实战Java高并发程序设计 7】让线程之间互相帮助--SynchronousQueue的实现
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
- 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
随机推荐
- linux运维面试前,先来检查这些基础知识忘了没?
知乎上有这样一个问题:一个新手面试 Linux 运维工作至少需要知道哪些知识?其中有一个答案对这一话题的解读非常深入,今天特别分享给大家. 一.什么是大型网站运维? 首先明确一下,全文所讲的”运维“是 ...
- 内核对象&句柄&泄漏&检测
今天看到这个问题如何评价王垠的 <讨厌的 C# IDisposable 接口>? - 王垠(人物),答案被歪到windows 内核对象和句柄,答案中谈的太浅显而且有误.翻出陈年老文章(此文 ...
- 服务器上的UID按钮
定位用的,比如你机柜上有很多台机器,你在前面按下UID灯,机器后面也有一个UID灯会亮起来,这样当你到后面去的时候你就知道刚才在前面看的是哪一台,另外,有人通过ILO远程端口连接到你的服务器的时候,U ...
- CSS3 -- 弹性盒
新版弹性盒 兼容到IE10及以上 flex小游戏 display: flex; 设置为弹性盒(父元素添加) flex-direction 用来来确定主轴的方向,从而确定基本的项目排列方向. 参数 说明 ...
- adreno的tbdr
看完apple的(&&powervr) 再来撸高通的.. FlexRender 能自己选三种模式 Direct Binning 这个只是分块 HWVizBinning 这个估计就是tb ...
- mysql数据库系统学习(一)---一条SQL查询语句是如何执行的?
本文基于----MySQL实战45讲(极客时间----林晓斌 )整理----->https://time.geekbang.org/column/article/68319 一.第一节:一条sq ...
- python 省略号 三个点...的含义
总结一下: 1.省略号在python里也是个对象. 2.=...(赋值号后面省略号),给该变量赋值一个default值.具体python的机制我不清楚.应该是在类里面定义好的. 3.: ...(冒号后 ...
- javascript内置对象一:String
<script> //string.split("-"),以字符"-"把string拆分成一个数组.返回一个数组 //array.joi ...
- encodeURI()、encodeURIComponent()、escape()
URI的通用格式如下: /*** 协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数1=值1&参数2=值2+值3#标志 **/ /*** http://use ...
- 2016 NEERC, Northern Subregional Contest G.Gangsters in Central City(LCA)
G.Gangsters in Central City 题意:一棵树,节点1为根,是水源.水顺着边流至叶子.该树的每个叶子上有房子.有q个询问,一种为房子u被强盗入侵,另一种为强盗撤离房子u.对于每个 ...