gitee.com/woood2/luca@v1.0.4/cmd/consumer/main.go (about) 1 package main 2 3 import ( 4 "context" 5 "gitee.com/woood2/luca/cmd/consumer/internal/alarm" 6 "gitee.com/woood2/luca/cmd/consumer/internal/handler" 7 _ "gitee.com/woood2/luca/cmd/consumer/internal/handler" 8 "gitee.com/woood2/luca/cmd/consumer/internal/subscriber" 9 lucaSDK "gitee.com/woood2/luca/cmd/micro/pkg" 10 "gitee.com/woood2/luca/internal/conf" 11 "gitee.com/woood2/luca/internal/discovery" 12 myLog "gitee.com/woood2/luca/internal/log" 13 "gitee.com/woood2/luca/internal/producer" 14 "gitee.com/woood2/luca/internal/status" 15 "gitee.com/woood2/luca/internal/trace" 16 "github.com/Shopify/sarama" 17 consulsd "github.com/go-kit/kit/sd/consul" 18 "go.uber.org/zap" 19 "log" 20 "os" 21 "os/signal" 22 "strings" 23 "sync" 24 "syscall" 25 "time" 26 ) 27 28 const entrance = "consumer" 29 30 func main() { 31 //config 32 attr := conf.Load("application.yml", "configs/application.yml") 33 //consul 34 client, consulClient := discovery.Client(attr.Consul.Host, attr.Consul.Port) 35 conf.MergeConsul(attr, consulClient) 36 //zap logger 37 logger := myLog.Build(attr.Env, attr.Project, entrance, attr.Host, attr.ConsoleLog) 38 defer logger.Sync() 39 //zipkin 40 trace.Open(attr.Zipkin) 41 defer trace.Close() 42 //sdk 43 setupSDK(client, logger) 44 //Pprof & prometheus & hystrix 45 go status.Pprof(attr.Pprof, attr.Env, attr.Consumer.PprofAddr) 46 go status.Prometheus(attr.Consumer.MetricsAddr) 47 go status.Hystrix(attr.Consumer.HystrixPort) 48 //alarm 49 alarm.WatchFunc(func(queue chan *alarm.Alarm) { 50 for { 51 a := <-queue 52 log.Printf("alarm watch: groupID=%s, topic=%s, partition=%d, retry=%d, value=%s\n", 53 a.GroupID, a.Msg.Topic, a.Msg.Partition, a.Retry, string(a.Msg.Value)) 54 } 55 }) 56 //sarama 57 time.Sleep(500 * time.Millisecond) 58 log.Println("Starting a new Sarama consumer") 59 wg := &sync.WaitGroup{} 60 ctx, cancel := context.WithCancel(context.Background()) 61 62 handler.RegisterHandlers(attr.Project, entrance, logger) 63 subs := subscriber.List() 64 for _, sub := range subs { 65 wg.Add(1) 66 go func(s *subscriber.Subscriber) { 67 defer wg.Done() 68 log.Printf("enter consume loop, topicName=%s, groupID=%s\n", s.TopicName, s.GroupID) 69 config := saramaConfig(attr.Kafka, s) 70 client, err := sarama.NewConsumerGroup(attr.Kafka.Brokers, s.GroupID, config) 71 if err != nil { 72 log.Panicf("Error creating consumer group client: %v", err) 73 } 74 gen := 0 75 delay := 3 * time.Second 76 for { 77 log.Printf("start consume session, topicName=%s, groupID=%s\n", s.TopicName, s.GroupID) 78 79 if err := client.Consume(ctx, strings.Split(s.TopicName, ","), s.ConsumerGroupHandler); err != nil { 80 if gen == 0 { 81 log.Panicf("Error from consumer: %v\n", err) 82 } else { 83 log.Printf("Error from consumer: %v, retry again in 3 seconds, gen=%d\n", err, gen) 84 time.Sleep(delay) 85 } 86 } 87 log.Printf("end consume session, topicName=%s, groupID=%s\n", s.TopicName, s.GroupID) 88 // check if context was cancelled, signaling that the consumer should stop 89 if ctx.Err() != nil { 90 if err = client.Close(); err != nil { 91 log.Panicf("Error closing client: %v\n", err) 92 } 93 log.Printf("quit consume loop, topicName=%s, groupID=%s\n", s.TopicName, s.GroupID) 94 return 95 } 96 gen++ 97 } 98 }(sub) 99 } 100 sigterm := make(chan os.Signal, 1) 101 signal.Notify(sigterm, syscall.SIGINT, syscall.SIGTERM) 102 select { 103 case <-ctx.Done(): 104 log.Println("terminating: context cancelled") 105 case <-sigterm: 106 log.Println("terminating: via signal") 107 } 108 cancel() 109 stopped := make(chan struct{}) 110 go func() { 111 wg.Wait() 112 close(stopped) 113 }() 114 t := time.NewTimer(5 * time.Second) 115 select { 116 case <-t.C: 117 log.Println("Server exiting in 5 sec...") 118 case <-stopped: 119 log.Println("Server exiting...") 120 } 121 } 122 123 func saramaConfig(c *conf.Kafka, g *subscriber.Subscriber) *sarama.Config { 124 verbose := false 125 if verbose { 126 sarama.Logger = log.New(os.Stdout, "[sarama] ", log.LstdFlags) 127 } 128 version, err := sarama.ParseKafkaVersion(c.Version) 129 if err != nil { 130 log.Panicf("Error parsing Kafka version: %v\n", err) 131 } 132 config := sarama.NewConfig() 133 config.Version = version 134 if g.OffsetOldest { 135 config.Consumer.Offsets.Initial = sarama.OffsetOldest 136 } 137 if c.EnableSASL { 138 config.Net.SASL.Enable = c.EnableSASL 139 config.Net.SASL.User = c.User 140 config.Net.SASL.Password = c.Password 141 config.Net.SASL.Handshake = true 142 if c.Algorithm == "sha512" { 143 config.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient { return &producer.XDGSCRAMClient{HashGeneratorFcn: producer.SHA512} } 144 config.Net.SASL.Mechanism = sarama.SASLTypeSCRAMSHA512 145 } else if c.Algorithm == "sha256" { 146 config.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient { return &producer.XDGSCRAMClient{HashGeneratorFcn: producer.SHA256} } 147 config.Net.SASL.Mechanism = sarama.SASLTypeSCRAMSHA256 148 } else { 149 log.Panicf("invalid SHA algorithm \"%s\": can be either \"sha256\" or \"sha512\"\n", c.Algorithm) 150 } 151 } 152 return config 153 } 154 155 func setupSDK(client consulsd.Client, zapLogger *zap.Logger) { 156 lucaClient := lucaSDK.NewSD(client, "weibo2", "todo", zapLogger, trace.ClientTrace()) 157 lucaSDK.SetGlobal(lucaClient) 158 //More... 159 }