Poslua Blog

「你是一个出色的程序员」要比「你是一个开发总监」要有意义的多

聊一聊字符串内部化

String Interning

缘起 字符串作为一种不可变值类型,在多数的语言里,其底层基本都是个只读的字节数组:一旦被创建,则不可被改写。正是因为其只读特性,如果有大量相同的字符串需要处理,那么在内存中就会保存多份,显然是非常浪费内存的。 对于 C 来说字符串本质上就是 const char*;而对于 Lua,虽然字符串并不是以 \0 结尾,但是 TString 的数据本质上也是一个 const char* ...

Golang 是否有必要内存对齐?

内存模型

有些同学可能不知道,struct 中的字段顺序不同,内存占用也有可能会相差很大。比如: type T1 struct { a int8 b int64 c int16 } type T2 struct { a int8 c int16 b int64 } 在 64 bit 平台上,T1 占用 24 bytes,T2 占用 16 bytes 大小;而在 32 bit 平台上...

线上一次大量 CLOSE_WAIT 复盘

redigo 的超时机制

最近,我在压测线上的一个长连接服务时,发现服务端出现大量的 CLOSE_WAIT 状态长时间不会释放,并且伴随着 goroutine 暴增,这里做个复盘,介绍下排查思路。 说起 CLOSE_WAIT,就不得不再复习一遍 TCP 的状态变迁: 出现 CLOSE_WAIT 本质上是因为服务端收到客户端的 FIN 后,仅仅回复了 ACK(由系统的 TCP 协议栈自动发出),并没有发 4 次...

Go 1.12 关于内存释放的一个改进

并不是内存泄露

一直以来 go 的 runtime 在释放内存返回到内核时,在 Linux 上使用的是 MADV_DONTNEED,虽然效率比较低,但是会让 RSS(resident set size 常驻内存集)数量下降得很快。不过在 go 1.12 里专门针对这个做了优化,runtime 在释放内存时,使用了更加高效的 MADV_FREE 而不是之前的 MADV_DONTNEED。具体可以参考这里: ...

Golang RabbitMQ 故障排查一例

断线重连的正确姿势

作为一个常识,当我们在处理一些长连接的业务时,客户端往往需要负责断线重连。比如,在我们的一个系统中,是这么处理 RabbitMQ 的断线重连的: func (c *Consumer) Start() error { if err := c.Run(); err != nil { return err } go c.ReConnect() return nil } func ...

Goroutine 泄露排查

pprof 无他

我们在发布一个 go 应用时,默认都会启用两个 http handler: 一个是 pprof,方便线上动态追踪问题;另外一个是 prometheus 的 metrics,这样就可以通过 grafana 准实时的监控当前 runtime 信息,及时预警。就像下面这样: package router import ( "net/http" _ "net/http/pprof" "g...

谈谈 Golang 中的 Data Race(续)

编译器是可以优化的, 并且没有 memory barrier

我在上一篇文章中曾指出:在 Go 的内存模型中,有 race 的 Go 程序的行为是未定义行为,理论上出现什么情况都是正常的。并尝试通过一段有 data race 的代码来说明问题: package main import ( "fmt" "runtime" "time" ) var i = 0 func main() { runtime.GOMAXP...

谈谈 Golang 中的 Data Race

到底啥是原子性

Any race is a bug 我在接手其他同事的 golang 项目时,一般都会习惯性的做一个竞态检测。有时总会得到一些“惊喜”,比如像下面这段代码: package main import ( "fmt" "runtime" "time" ) var i = 0 func main() { runtime.GOMAXPROCS(2) ...

说下 Kong 的非主流 Service Mesh 之路

Service Mesh

转载自 聊一聊微服务网关 kong 近期的模型变迁 我也不喜欢最新的 Kong Service 模型,这里讨论一些我曾经的疑问。 在 0.13.X 版本之前,Kong 的核心域模型名为 API Object Routes,从 0.13.X 版本开始,Kong 引入了 Service/Route Object,把 API Object 标记为 deprecated。在当前的 1.1...

Golang Dep 依赖冲突处理

Dep Dependencies

对于 Golang 应用内存堆栈的监控,基本都是读取 runtime.MemStats,然后发往一些 TSDB 进行可视化展示。代码一般都是这样的: memStats := &runtime.MemStats{} runtime.ReadMemStats(memStats) 如果希望获取 GC 状态,可以这样: gcstats := &debug.GCStats{Pa...