虽然使用 Goland 在 Windows 上开发 go 程序非常方便,但是有些场景,必须在 Linux 环境上进行调试,所以抽会研究了一下,还是非常方便的。不了解的小伙伴,可以按照我的方法尝试一下。
这是一个通过 go-micro broker 使用 kafka 的 demo
!!!<-time.After(time.Second * 360)!!!, 由于 main 函数中启动了两个 goroutine, 若此处 sleep 的时间不够长,我们的 debug 很容易会因为 main 所在的 goroutine 而退出。可能对 debug 造成比较大的困惑,请注意。
package main
import (
"fmt"
"log"
"time"
"github.com/micro/go-micro/v2/broker"
"github.com/micro/go-micro/v2/config/cmd"
_ "github.com/micro/go-plugins/broker/kafka/v2"
)
var (
topic = "go.micro.topic.foo"
)
func pub() {
tick := time.NewTicker(time.Second)
i := 0
for _ = range tick.C {
msg := &broker.Message{
Header: map[string]string{
"id": fmt.Sprintf("%d", i),
},
Body: []byte(fmt.Sprintf("%d: %s", i, time.Now().String())),
}
if err := broker.Publish(topic, msg); err != nil {
log.Printf("[pub] failed: %v", err)
} else {
fmt.Println("[pub] pubbed message:", string(msg.Body))
}
i++
}
}
func sub() {
_, err := broker.Subscribe(topic, func(p broker.Event) error {
fmt.Println("[sub] received message:", string(p.Message().Body), "header", p.Message().Header)
return nil
})
if err != nil {
fmt.Println(err)
}
}
func main() {
cmd.Init()
if err := broker.Init(); err != nil {
log.Fatalf("Broker Init error: %v", err)
}
if err := broker.Connect(); err != nil {
log.Fatalf("Broker Connect error: %v", err)
}
go pub()
go sub()
<-time.After(time.Second * 360)
}
module demo1
go 1.13
go build -gcflags=all="-N -l" ## 必须这样编译,才能用gdb打印出变量,第二个是小写的L,不是大写的i
由于 main.go 中与引用库中冲突,重新修改
$ dlv exec ./demo1 -- -broker kafka -broker_address 192.168.0.111:9092
Type 'help' for list of commands.
(dlv) b main.go:47
Command failed: Location "main.go:47" ambiguous: /home/luojie/gopath/pkg/mod/github.com/nats-io/[email protected]/main.go, /home/luojie/test/go/go-micro-kafka/demo1/main.go…
加上路径之后,就可以解决文件名冲突的问题
(dlv) b demo1/main.go:47
Breakpoint 1 set at 0xe9ab98 for main.main() ./main.go:47
(dlv) c
> main.main() ./main.go:47 (hits goroutine(1):1 total:1) (PC: 0x131c59f)
42: fmt.Println(err)
43: }
44: }
45:
46: func main() {
=> 47: cmd.Init()
48:
49: if err := broker.Init(); err != nil {
50: log.Fatalf("Broker Init error: %v", err)
51: }
52: if err := broker.Connect(); err != nil {
可以看到测试断点可以正常工作,此时我要增加其它断点,我真正关注的位置: 我想了解怎么从 kafka 中取出数据的
(dlv) b consumer_group.go:552
Breakpoint 2 set at 0x12b71bb for github.com/Shopify/sarama.newConsumerGroupSession() /home/luojie/gopath/pkg/mod/github.com/!shopify/[email protected]/consumer_group.go:552
使用 bt 指令可以非常方便看到调用顺序,非常方便研究源码
> github.com/Shopify/sarama.newConsumerGroupSession() /home/luojie/gopath/pkg/mod/github.com/!shopify/[email protected]/consumer_group.go:552 (hits goroutine(31):1 total:1) (PC: 0x12b71bb)
547: waitGroup sync.WaitGroup
548: releaseOnce sync.Once
549: hbDying, hbDead chan none
550: }
551:
=> 552: func newConsumerGroupSession(ctx context.Context, parent *consumerGroup, claims map[string][]int32, memberID string, generationID int32, handler ConsumerGroupHandler) (*consumerGroupSession, error) {
553: // init offset manager
554: offsets, err := newOffsetManagerFromClient(parent.groupID, memberID, generationID, parent.client)
555: if err != nil {
556: return nil, err
557: }
(dlv) bt
0 0x00000000012b71bb in github.com/Shopify/sarama.newConsumerGroupSession
at /home/luojie/gopath/pkg/mod/github.com/!shopify/[email protected]/consumer_group.go:552
1 0x00000000012b3fa1 in github.com/Shopify/sarama.(*consumerGroup).newSession
at /home/luojie/gopath/pkg/mod/github.com/!shopify/[email protected]/consumer_group.go:298
2 0x00000000012b2e71 in github.com/Shopify/sarama.(*consumerGroup).Consume
at /home/luojie/gopath/pkg/mod/github.com/!shopify/[email protected]/consumer_group.go:169
3 0x000000000131b484 in github.com/micro/go-plugins/broker/kafka.(*kBroker).Subscribe.func1
at /home/luojie/gopath/pkg/mod/github.com/micro/go-plugins/broker/[email protected]/kafka.go:200
4 0x0000000000465e71 in runtime.goexit
at /home/luojie/go/src/runtime/asm_amd64.s:1357