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  }