服务启动的时候,好像处理的并不完善呢?

服务启动的时候,好像处理的并不完善呢?

	ctx, cancel := context.WithCancel(context.Background())
	a.cancel = cancel
	eg, ctx := errgroup.WithContext(ctx)
	wg := sync.WaitGroup{}

	for _, srv := range servers {
		srv := srv

		//2、再启动一个goroutine 去监听是否有err产生
		eg.Go(func() error {
			<-ctx.Done()
			sctx, cancel := context.WithTimeout(context.Background(), a.opts.stopTimeout)
			defer cancel()
			return srv.Stop(sctx)
		})
		wg.Add(1)
		//1、启动server
		eg.Go(func() error {
			wg.Done()
			log.Info("start server")
			return srv.Start(ctx)
		})
	}

	wg.Wait()

老师这是项目的代码是不是有BUG?

你讲的时候有三种情况:

如果一个server启动失败剩余的的server状态:

  1. 还没开始start。解决方法:不进行start(直接stop)
  2. start进行中、解决方法:cancel start
  3. start已经完成。解决方法: 调用stop

对于 2 的情况,代码里并没有手动 处理 cancel 信号啊?!cancel信号只是促使执行Stop方法,正在执行一半的Start不是依旧会继续执行?

而对于 1 的情况,剩余的server还没执行Start方法,直接调用Stop,但是直接调用Stop也并没有终止Start方法啊?!

而且甚至对于 restServer 包里的server(Server wrapper for gin.Engine),这个server初始化的过程就在Start方法中,假设现在收到了cancel信号,直接调用的Stop方法,但是Stop方法中用到了server,此时若Start方法没执行完,连server都没初始化完成,不就panic了?
图片描述

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

2回答
bobby 2023-05-07 21:13:14

你这里还是因为对context原理理解不够, https://img1.sycdn.imooc.com//climg/6457a35009036d0711760589.jpg 当errorgroup调用cancel的时候,这里的ctx.Done就能收到取消消息,这里就会执行stop方法了, 也就是所有的server启动的时候同时会启动一个监听取消的ctx,所有任何地方只要对context调用了cancel了,所有的server都会监听到这个消息执行stop操作, 这里的cancel就是errorgroup调用的

  • 提问者 努力学习啊啊 #1

    是的,但是:stop和Start是两个协程,只有包含stop的协程监听cancel信号,现在假设第一个服务启动失败,触发cancel,第二个server包含stop的协程 有代码 :<-ctx.Done()执行stop,但是包含Start的协程没有<-ctx.Done()这样的代码,start协程的逻辑依旧继续执行,最终启动服务,这种情况怎么解决?

    2023-05-07 21:27:50
  • 提问者 努力学习啊啊 #2

    stop函数调用shutdown之后,start函数才执行到 监听服务的地方,这样不就一个失败一个成功了? 

    2023-05-07 21:30:31
  • bobby 回复 提问者 努力学习啊啊 #3

    这里for循环的时候已经将每个server都启动了一个 包含上述<-ctx.Done()的逻辑了,怎么会无法调用stop?

    2023-05-07 21:33:14
bobby 2023-05-04 20:26:38

这些errorgroup会去自动调用的,课程中讲解过errorgroup的源码的

  • 提问者 努力学习啊啊 #1

    errogroup不会处理我说的 1、2情况吧,项目中就这用到的errorgroup:

    https://img1.sycdn.imooc.com//climg/6453b549097e0dac10960711.jpg



    https://img1.sycdn.imooc.com//climg/6453b57f09fcb5b606840588.jpg


    这里只是其中server一个失败,从而调用cancel,怎么解决1、2的情况,直接终止Start方法的?

    2023-05-04 21:40:22
  • 提问者 努力学习啊啊 #2

    errorgroup源码里就是调用cancel把? 怎么调用cancel,只是促使执行 Stop()。而Start()方法被包在eg.Go()中,并不会被终止。https://img1.sycdn.imooc.com//climg/6453b6e409bacd5a05530150.jpg

    https://img1.sycdn.imooc.com//climg/6453b77209ed646b04970582.jpg

    2023-05-04 21:47:32
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
Go开发工程师全新版
  • 参与学习       490    人
  • 解答问题       559    个

风口上的技术,薪资水平遥遥领先,现在学习正值红利期! 未来3-5年,Go语言势必成为企业高性能项目中不可替代的语言 从基础到项目实战再到重构,对转行人员友好,真正从入门到精通!

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师