设为首页 加入收藏

TOP

golang微服务框架go-micro 入门笔记2.4 go-micro service解读(二)
2019-09-04 00:56:33 】 浏览:117
Tags:golang 服务 框架 go-micro 入门 笔记 2.4 service 解读
_, o := range opts { o(&s.opts) } s.once.Do(func() { // Initialise the command flags, overriding new service _ = s.opts.Cmd.Init( cmd.Broker(&s.opts.Broker), cmd.Registry(&s.opts.Registry), cmd.Transport(&s.opts.Transport), cmd.Client(&s.opts.Client), cmd.Server(&s.opts.Server), ) }) }

for _, o := range opts代码片段的作用是设置service的属性,底层也是通过 类似o.Server.Init(server.NaME(n)来实现的。

s.once.Do(func) 这里利用了sync.Once特性,这里预示着func只会运行1次。

micro.NewService的函数调用关系如下

两行传入的参数通过c := a.Command(name)来获得需要运行的命令行

service.Run

源代码如下

func (s *service) Run() error {
    // 这一段代码的作用其实只开启调试支持
    s.opts.Server.Handle(
        s.opts.Server.NewHandler(
            handler.DefaultHandler,//默认处理脚本handler就是调试
            server.InternalHandler(true),//把这个标记为成内置的handler
        ),
    )

    if err := s.Start(); err != nil {
        return err
    }

    ch := make(chan os.Signal, 1)
    signal.Notify(ch, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT)

    select {
    // wait on kill signal
    case <-ch:
    // wait on context cancel
    case <-s.opts.Context.Done():
    }

    return s.Stop()
}

s.Start()作用是启动服务,目前micro支持的rpcservce/httpservice/apiservice/websercice等,他们都实现了这个Start()方法。以RPCService为例,函数流程如下

micro.NewService的函数调用关系如下

具体代码解读如下

func (s *rpcServer) Start() error {
    config := s.Options()

    //启动监听
    ts, err := config.Transport.Listen(config.Address)
    if err != nil {
        return err
    }


    // 连接消息代理
    if err := config.Broker.Connect(); err != nil {
        return err
    }


    // 注册发现,严格校验注册服务,
    if err = s.opts.RegisterCheck(s.opts.Context); err != nil {
        log.Logf("Server %s-%s register check error: %s", config.Name, config.Id, err)
    } else {
        // 注册发现,匿名注册
        if err = s.Register(); err != nil {
            log.Logf("Server %s-%s register error: %s", config.Name, config.Id, err)
        }
    }

    exit := make(chan bool)

    //启动监听服务
    go func() {
        for {
            // 监听
            err := ts.Accept(s.ServeConn)

            // TODO: listen for messages
            // msg := broker.Exchange(service).Consume()

            select {
            // check if we're supposed to exit
            case <-exit:
                return
            // check the error and backoff
            default:
                if err != nil {
                    log.Logf("Accept error: %v", err)
                    time.Sleep(time.Second)
                    continue
                }
            }

            // no error just exit
            return
        }
    }()

    //开启定时注册携程
    go func() {
        t := new(time.Ticker)

        // only process if it exists
        if s.opts.RegisterInterval > time.Duration(0) {
            // new ticker
            t = time.NewTicker(s.opts.RegisterInterval)
        }

        // return error chan
        var ch chan error

    Loop:
        for {
            select {
            // register self on interval
            case <-t.C:
                s.RLock()
                registered := s.registered
                s.RUnlock()
                //校验注册
                if err = s.opts.RegisterCheck(s.opts.Context); err != nil && registered {
                    log.Logf("Server %s-%s register check error: %s, deregister it", config.Name, config.Id, err)
                    // deregister self in case of error
                    if err := s.Deregister(); err != nil {
                        log.Logf("Server %s-%s deregister error: %s", config.Name, config.Id, err)
                    }
                } else {
                    //匿名注册
                    if err := s.Register(); err != nil {
                        log.Logf("Server %s-%s register error: %s", config.Name, config.Id, err)
                    }
                }
            // wait for exit
            case ch = <-s.exit:
                t.Stop()
                close(exit)
                break Loop
            }
        }

        // 如果退出来了,那么注销服务
        if err := s.Deregister(); err != nil {
            log.Logf("Server %s-%s deregister error: %s", config.Name, config.Id, err)
        }

        // 等到请求完成
        if s.wg != nil {
            s.wg.Wait()
        }

        // 关闭
        ch <- ts.Close()

        // 关闭消息代理连接
        config.Broker.Disconnect()

        // swap back address
        s.Lock()
        s.opts.Address = addr
        s.Unlock()
    }()

    ret
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇解决vscode中golang插件依赖安装.. 下一篇深度解密Go语言之 scheduler

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目