etcd源码阅读1

etcd code reading 1

Posted by BY on November 16, 2020

前言

同学最近工作之余在看一些开源源码。我觉得我也不能太落后,在10月的末尾,开始尝试阅读etcd的源码。

正文

阅读源码前的准备工作:

在 https://github.com/coreos/go-systemd 下载go-systemd-master,将其内容(解压不含go-systemd-master目录)放$GOROOT/src/github.com/go-systemd
在 https://github.com/spf13/cobra 下载cobra-master,将其内容放$GOROOT/src/github.com/cobra
在 https://github.com/uber-go/zap 下载zap-master,将其内容放$GOROOT/src/go.uber.org/zap
在 https://github.com/etcd-io/etcd 下载etcd-master,将其内容放$GOROOT/src/go.etcd.io/etcd,随后用IDEA打开$GOROOT/src/go.etcd.io/

etcd简介

etcd是一个高可用的分布式的键值数据库,基于github开源,提供配置共享和服务发现的集群服务。通常我们一般用来存储数据的链接,缓存配置等的自动发现和更新。 这一系列就是通过对etcd的源码的解读,去弄懂商用的raft以及grpc等的使用和设计,同时也会介绍一下,其所使用的的一些开源的库的精彩设计。

首先我们从etcd的main方法开始,

func main() {
    etcdmain.Main()
}

很简单,进入到etcdmain.Main之后,

func Main() {
    checkSupportArch()//检查系统是否支持

    if len(os.Args) > 1 {//获取入参,
        cmd := os.Args[1]//获取启动命令
        if covArgs := os.Getenv("ETCDCOV_ARGS"); len(covArgs) > 0 {
            args := strings.Split(os.Getenv("ETCDCOV_ARGS"), "\xe7\xcd")[1:]
            rootCmd.SetArgs(args)
            cmd = "grpc-proxy"
        }
    switch cmd {//根据命令启用程序
        case "gateway", "grpc-proxy":
            if err := rootCmd.Execute(); err != nil {
                fmt.Fprint(os.Stderr, err)
                os.Exit(1)
            }
            return
        }
    }

    startEtcdOrProxyV2()
}

在github上etcd/etcdctl/ctlv2/ctl_cov.go文件的提交信息显示etcdctl, e2e: use 0xe7cd as argument separator in cov-enabled etcdctl这一段话,使用0xe7cd标记作为分隔。

func checkSupportArch() {
	// TODO qualify arm64
	if runtime.GOARCH == "amd64" || runtime.GOARCH == "ppc64le" {
		return
	}
	// unsupported arch only configured via environment variable
	// so unset here to not parse through flag
	defer os.Unsetenv("ETCD_UNSUPPORTED_ARCH")
	if env, ok := os.LookupEnv("ETCD_UNSUPPORTED_ARCH"); ok && env == runtime.GOARCH {
		fmt.Printf("running etcd on unsupported architecture %q since ETCD_UNSUPPORTED_ARCH is set\n", env)
		return
	}

	fmt.Printf("etcd on unsupported platform without ETCD_UNSUPPORTED_ARCH=%s set\n", runtime.GOARCH)
	os.Exit(1)
}

如果是amd和ppc64le架构是能够支持的架构(可以使用go env查看runtime.GOARCH),不支持的架构要提前设置ETCD_UNSUPPORTED_ARCH系统环境变量(退出会重置ETCD_UNSUPPORTED_ARCH环境变量),不支持并且没有设置ETCD_UNSUPPORTED_ARCH,则程序终止。
上面仔细去看,是根据命令行输入的第一个参数去启动不同的代码逻辑,我们来查看一下etcd命令的使用帮助:

$ ./etcd -help
Usage:

  etcd [flags]
    Start an etcd server.

  etcd --version //查看版本
    Show the version of etcd.

  etcd -h | --help //获取帮助
    Show the help information about etcd.

  etcd --config-file //设置配置文件
    Path to the server configuration file.

  etcd gateway //启动 L4 TCP网关代理
    Run the stateless pass-through etcd TCP connection forwarding proxy.

  etcd grpc-proxy //L7 grpc 代理
    Run the stateless etcd v3 gRPC L7 reverse proxy.

........

注意看上面的最后两个说明:

gateway 无状态的tcp转发服务 grpc-proxy 无状态grpc服务 可以从代码逻辑看到,可以有3个启动命令服务,

 ./etcd //启动etcd服务
 ./etcd gateway start //启动tcp网关代理
 ./etcd grpc-proxy start //启动grpc网关代理

我们主要也是从这三个命令去贯穿整个etcd的源码去介绍。