Go 服务器框架遇到的问题
读写分离
Go 在往 chan 里写数据的时候, 是没有办法判断该 chan 是否是关闭的, 此时必须要加上一个标志位, 在发送之前判断一下
正常情况下是可行的, 但是在压测的时候还是会出现往一个已经关闭的 chann 写数据 panic 的情况
于是想过几种方法
将标志位的判断和发送语句放在一起, 尽量缩短两句执行的时间差, 代码如下
if this.isClosed == true { return } msg <- data
测试的时候没有出现 panic 的概率会变小, 但还是会有出现的情况, 猜想可知多核的情况下 msg 还是可能在两条语句中间被关闭掉
我想到的最好的方法就是 msg 不能再其他 goroutine 被关闭, 只和发送数据的函数在同一个 goroutine, 代码如下
select { case <-this.ExitChan: close(this.msgChan) return nil case this.msgChan <- msg: }
日志问题
由于日志会在在并发的情况下写文件,想达到顺序写入必然涉及到加锁
自己的日志需要加一些额外的信息,所以不会直接调用 log 库
在上层需要封装一些信息,也要加锁,于是把 log 库的内容取出来,重新封装一下 这样就不用加两次锁
goroutine 泄漏
func runTask(id int) string { time.Sleep(10 * time.Millisecond) return fmt.Sprintf("The result is from %d", id) } func FirstRsp() string { num := 10 ch := make(chan string) for i := 0; i < num; i++ { go func(i int) { ret := runTask(i) ch <- ret }(i) } return <-ch } func TestFirstrsp(t *testing.T) { t.Log("before:", runtime.NumGoroutine()) t.Log(FirstRsp()) time.Sleep(time.Second) t.Log("after:", runtime.NumGoroutine()) }
此处FirstRsp 接收到 ch 的值之后就返回,有9个goroutine 会阻塞在 ch 的发送上,造成泄漏
如果将 ch 改成 buff chan 就可以解决泄漏的问题