github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/cmd/puppeth/module_ethstats.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2017 Go Ethereum作者 10 //此文件是Go以太坊的一部分。 11 // 12 //Go以太坊是免费软件:您可以重新发布和/或修改它 13 //根据GNU通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊的分布希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU通用公共许可证了解更多详细信息。 21 // 22 //你应该已经收到一份GNU通用公共许可证的副本 23 //一起去以太坊吧。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package main 26 27 import ( 28 "bytes" 29 "fmt" 30 "math/rand" 31 "path/filepath" 32 "strconv" 33 "strings" 34 "text/template" 35 36 "github.com/ethereum/go-ethereum/log" 37 ) 38 39 //ethstatsDockerfile是构建ethstats后端所需的Dockerfile。 40 //以及相关的监测站点。 41 var ethstatsDockerfile = ` 42 FROM puppeth/ethstats:latest 43 44 RUN echo 'module.exports = {trusted: [{{.Trusted}}], banned: [{{.Banned}}], reserved: ["yournode"]};' > lib/utils/config.js 45 ` 46 47 //ethstatscomposefile是部署和 48 //维护一个ethstats监控站点。 49 var ethstatsComposefile = ` 50 version: '2' 51 services: 52 ethstats: 53 build: . 54 image: {{.Network}}/ethstats{{if not .VHost}} 55 ports: 56 - "{{.Port}}:3000"{{end}} 57 environment: 58 - WS_SECRET={{.Secret}}{{if .VHost}} 59 - VIRTUAL_HOST={{.VHost}}{{end}}{{if .Banned}} 60 - BANNED={{.Banned}}{{end}} 61 logging: 62 driver: "json-file" 63 options: 64 max-size: "1m" 65 max-file: "10" 66 restart: always 67 ` 68 69 //deployethstats通过ssh将新的ethstats容器部署到远程计算机, 70 //Docker和Docker组合。如果具有指定网络名称的实例 71 //已经存在,将被覆盖! 72 func deployEthstats(client *sshClient, network string, port int, secret string, vhost string, trusted []string, banned []string, nocache bool) ([]byte, error) { 73 //生成要上载到服务器的内容 74 workdir := fmt.Sprintf("%d", rand.Int63()) 75 files := make(map[string][]byte) 76 77 trustedLabels := make([]string, len(trusted)) 78 for i, address := range trusted { 79 trustedLabels[i] = fmt.Sprintf("\"%s\"", address) 80 } 81 bannedLabels := make([]string, len(banned)) 82 for i, address := range banned { 83 bannedLabels[i] = fmt.Sprintf("\"%s\"", address) 84 } 85 86 dockerfile := new(bytes.Buffer) 87 template.Must(template.New("").Parse(ethstatsDockerfile)).Execute(dockerfile, map[string]interface{}{ 88 "Trusted": strings.Join(trustedLabels, ", "), 89 "Banned": strings.Join(bannedLabels, ", "), 90 }) 91 files[filepath.Join(workdir, "Dockerfile")] = dockerfile.Bytes() 92 93 composefile := new(bytes.Buffer) 94 template.Must(template.New("").Parse(ethstatsComposefile)).Execute(composefile, map[string]interface{}{ 95 "Network": network, 96 "Port": port, 97 "Secret": secret, 98 "VHost": vhost, 99 "Banned": strings.Join(banned, ","), 100 }) 101 files[filepath.Join(workdir, "docker-compose.yaml")] = composefile.Bytes() 102 103 //将部署文件上载到远程服务器(然后清理) 104 if out, err := client.Upload(files); err != nil { 105 return out, err 106 } 107 defer client.Run("rm -rf " + workdir) 108 109 //构建和部署ethstats服务 110 if nocache { 111 return nil, client.Stream(fmt.Sprintf("cd %s && docker-compose -p %s build --pull --no-cache && docker-compose -p %s up -d --force-recreate --timeout 60", workdir, network, network)) 112 } 113 return nil, client.Stream(fmt.Sprintf("cd %s && docker-compose -p %s up -d --build --force-recreate --timeout 60", workdir, network)) 114 } 115 116 //ethstatsInfo从ethstats状态检查返回以允许报告 117 //各种配置参数。 118 type ethstatsInfos struct { 119 host string 120 port int 121 secret string 122 config string 123 banned []string 124 } 125 126 //报表将类型化结构转换为纯字符串->字符串映射,其中包含 127 //大多数(但不是全部)字段用于向用户报告。 128 func (info *ethstatsInfos) Report() map[string]string { 129 return map[string]string{ 130 "Website address": info.host, 131 "Website listener port": strconv.Itoa(info.port), 132 "Login secret": info.secret, 133 "Banned addresses": strings.Join(info.banned, "\n"), 134 } 135 } 136 137 //check ethstats对ethstats服务器执行运行状况检查,以验证 138 //它正在运行,如果是,收集有关它的有用信息。 139 func checkEthstats(client *sshClient, network string) (*ethstatsInfos, error) { 140 //检查主机上可能的ethstats容器 141 infos, err := inspectContainer(client, fmt.Sprintf("%s_ethstats_1", network)) 142 if err != nil { 143 return nil, err 144 } 145 if !infos.running { 146 return nil, ErrServiceOffline 147 } 148 //从主机或反向代理解析端口 149 port := infos.portmap["3000/tcp"] 150 if port == 0 { 151 if proxy, _ := checkNginx(client, network); proxy != nil { 152 port = proxy.port 153 } 154 } 155 if port == 0 { 156 return nil, ErrNotExposed 157 } 158 //从反向代理解析主机并配置连接字符串 159 host := infos.envvars["VIRTUAL_HOST"] 160 if host == "" { 161 host = client.server 162 } 163 secret := infos.envvars["WS_SECRET"] 164 config := fmt.Sprintf("%s@%s", secret, host) 165 if port != 80 && port != 443 { 166 config += fmt.Sprintf(":%d", port) 167 } 168 //检索IP黑名单 169 banned := strings.Split(infos.envvars["BANNED"], ",") 170 171 //运行健全检查以查看端口是否可访问 172 if err = checkPort(host, port); err != nil { 173 log.Warn("Ethstats service seems unreachable", "server", host, "port", port, "err", err) 174 } 175 //容器可用,组装并返回有用的信息 176 return ðstatsInfos{ 177 host: host, 178 port: port, 179 secret: secret, 180 config: config, 181 banned: banned, 182 }, nil 183 }