未加星标

Go初体验

字体大小 | |
[数据库(综合) 所属分类 数据库(综合) | 发布者 店小二04 | 时间 2017 | 作者 红领巾 ] 0人收藏点击收藏

最近在一个项目中使用了Go语言,当然不可避免的遇到了一些问题,记录这些问题的解决方法,也算是Go初体验的一部分了。

项目中的需求很简单,从RabbitMQ读数据,然后写入Redis当中,当然这个量比较大,似乎用goroutine是一个好的解决办法。

所以刚开始的逻辑是,从MQ读取数据,然后对每个数据都用一个goroutine处理。goroutine从Redis Pool里面取Redis connection,然后写数据到Redis。Redis go library redigo ,库中提供Redis Pool的API,可以很方便的管理Redis connection。

func HandlePackage(data){ redisConn := getConnFromPool() wirteRedis(data) } func main(){ for package from MQ { go HandlePackage(package) } } 问题1: no such host

结果一跑,就出现很多 “no such host” 错误,google了一下,发现是glibc的 bug 。当并发很高的时候,glibc库中查找DNS的代码就会出错。根据bug描述,要么升级glibc到2.20(但是2.20版本还没有发布),要么重新编译Go的net库。于是重新编译了Go的net库后,新问题又出现了。

问题2: redis connection timeout

这次是跑着跑着,Redis很多connection都timeout了,于是仔细看了一下redigo的Pool文档,发现默认Pool是没有大小限制的,如果Pool里面没有connection,会一直创建。难怪会timeout,应该是MQ数据太多,起了太多的goroutine,所以就会创建很多Redis client,Redis Server顶不住了。

想着限制一下Pool的大小,但是看了redigo的 issue ,发现如果限制大小,当Pool没有资源时,Get会直接返回error。

于是根据redigo的wiki,采用了youtube开源的vitess的一个 Pool ,这个pool限制大小后,当资源耗尽时,再请求会阻塞,直到Pool里面有可用资源才返回。

问题3: high memory usage

这次修改后,跑着跑着,发现进程的内存一直在增长,用top命令看,发现内存的 Res 一直飙升到1.8g,采用go自带的profile工具,发现sys和Stack sys都非常高,相反heap相应的项占用都非常少,看来不是内存泄漏的问题。

从profile上看,有时候goroutine会飙升到100k,估计内存居高不下跟goroutine有关。查阅了一下,发现在Go1.3中,存在一个 bug 。goroutine消耗的资源,并不会释放,相反会存放在pool中,等待下次新建goroutine时使用。于是进程的内存只会增加,不会减少。

分析了一下原因,有可能是网络不好,或者Redis在做bgsave或者其它操作,导致写Redis变慢,这样数据的生产(从MQ拿数据)比数据消费(写数据到Redis)快的多,而Redis connection又限制数量,导致goroutine阻塞在从pool取Reids connection上面,于是会创建越来越多的goroutine,结果就是导致内存一直飙升,却不会释放。

后来在 golang-nuts 邮件列表上问了问,有个老外建议用channel做信号量,来控制goroutine的数量,这样在高峰或者特殊情况,就不会导致goroutine无限制增长。

c := make(chan bool, 50) // concurrency = 50 for <whatever> { c <- true // blocks if the channel is full go func() { defer func() { <-c } // make room for another goroutine // do whatever the goroutine should do } }

修改代码后,发现goroutine限制数量后,内存基本控制在200多M以内,不会有占用大内存的现象出现了。

当然现在还是Go的初级使用者,这种消费者比生产者慢的需求,用Go的buffered channel是否合适,有没有更合适的解决方法,还待进一步研究。

Reference

本文数据库(综合)相关术语:系统安全软件

分页:12
转载请注明
本文标题:Go初体验
本站链接:http://www.codesec.net/view/561395.html
分享请点击:


1.凡CodeSecTeam转载的文章,均出自其它媒体或其他官网介绍,目的在于传递更多的信息,并不代表本站赞同其观点和其真实性负责;
2.转载的文章仅代表原创作者观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,本站对该文以及其中全部或者部分内容、文字的真实性、完整性、及时性,不作出任何保证或承若;
3.如本站转载稿涉及版权等问题,请作者及时联系本站,我们会及时处理。
登录后可拥有收藏文章、关注作者等权限...
技术大类 技术大类 | 数据库(综合) | 评论(0) | 阅读(10)