go channe笔记
2016-07-17 00:17
225 查看
最近使用go写了一个爬虫监控系统,每秒大概处理十次请求,得到数据后进行数据库处理,并将数据转发给websocket到前端展示。
开始测试的时候没有问题,但是一上线接受真是数据时就会运行半小时后出现无法响应服务还有出了我有一句打印请求的body在打印信息我的其他逻辑全部没有运行了,最开始百思不得其解。
最开始我的代码是这样子的:func (this *MainController) Post() { defer this.Ctx.Request.Body.Close() body, err := ioutil.ReadAll(this.Ctx.Request.Body) fmt.Println(string(body)) go RecodeBody(body) if err == nil && body != nil { models.Messages <- body: this.Data["json"] = "ok" } else { this.Data["json"] = "fail" } this.ServeJSON() }
然后我再RecodeBody()方法中进行一些逻辑处理之后并在数据库操作之前也有可能向models.Messages中写入。
models.Messages 是一个有1000缓存的channel并是转发消息到websocket的缓存。
在第一次实际数据测试时运行半小时后出现只答应请求body的情况之后思考了半天终于找到了问题的所在:
问题出在了当向websocket写入信息时如果因为网络或者连接数较多时可能一条消息要花比接受一天消息的时间去处理,等到半个小时的时候channel的缓存装满了,导致堵塞,于是
this.ServeJSON()不能运行所以无法返回信息。然后应为我的逻辑处理函数中也会向channel写入信息,也导致堵塞。所以导致了我服务器约等于死点的假象。
我想导致我遇到这个问题的主要原因是自己对go channel的不够了解还有写代码时急于实现功能而没有去注意代码的逻辑与质量。
知道了问题所在问题总是好解决的,于是我把给Messages发送消息全部交给了
RecodeBody()函数,并也通过一个channel给它船体数据,并给这个channel发送信息加上default以避免堵塞。
func (this *MainController) Post() { defer this.Ctx.Request.Body.Close() body, err := ioutil.ReadAll(this.Ctx.Request.Body) fmt.Println(string(body)) if err == nil && body != nil { select { case models.PS <- body: this.Data["json"] = "ok" default: this.Data["json"] = "server is busy" } } else { this.Data["json"] = "fail" } this.ServeJSON() }
这样子就无论如何都不会出现无响应的情况,除非你的机器实在是受不了那么大的并发量。
总结:
在处理有一定并发量的时候使用channel时,写入信息到channel时劲量使用
select { case models.PS <- body: this.Data["json"] = "ok" default: this.Data["json"] = "server is busy" }
格式,以免当channel因为消费不及时导致缓存用光的情况而没有提示信息,让你不好追溯问题所在。
相关文章推荐
- SQLSERVER 中GO的作用详解
- 在Go语言程序中使用gojson来解析JSON格式文件
- 举例详解Go语言中os库的常用函数用法
- Go语言中函数的参数传递与调用的基本方法
- 深入解析Go语言的io.ioutil标准库使用
- GO语言的IO方法实例小结
- Go语言的os包中常用函数初步归纳
- Go语言中数组的基本用法演示
- GO语言类型转换和类型断言实例分析
- 深入解析Go语言编程中的递归使用
- 初步解读Golang中的接口相关编写方法
- Go语言实现的最简单数独解法
- 详解Golang编程中的常量与变量
- Go实现比较时间大小
- 深入剖析Go语言编程中switch语句的使用
- 简单讲解Go程序中使用MySQL的方法
- Go语言的Windows下环境配置以及简单的程序结构讲解
- 在Go程序中实现服务器重启的方法
- Go语言流程控制之goto语句与无限循环
- 在Mac OS上安装Go语言编译器的方法