OpenFaaS接口

翻译自: https://blog.alexellis.io/the-power-of-interfaces-openfaas/ 2019年5月28日
首发于:http://hiknowledge.top/2019/12/27/openfaas%e6%8e%a5%e5%8f%a3/

在这篇文章中,我将探索如何将接口的思想引入OpenFaaS,以使项目适应不断变化的容器环境。您将了解如何通过提供程序模型和faas-provider SDK扩展OpenFaaS。然后,我将向您介绍为什么我们要构建faas-cli generate命令,它的作用,以及如何使用它来为Kubernetes生成CRD。

OpenFaaS架构介绍

一开始有OpenFaaS, OpenFaaS只在Docker Swarm上运行。

四个月后,一个名为Kubernetes的容器编配平台的需求也出现了,该平台的吸引力和业界的接受度都在增长。回顾历史,很难想象 Kubernetes 并不总是容器战争的赢家。

当时,OpenFaaS网关和API接口的集群实现是紧密耦合的。

Provider模型

因此,我将OpenFaaS网关现有的REST API分为三个组件——网关、提供者接口和faas-swarm。 其思想是,提供者可以接入任何容器编制器,并了解如何在不更改接口或工具的情况下执行CRUD、伸缩和调用

这意味着网关组件不需要像Kubernetes的client-go包那样有大量的依赖关系而膨胀起来,这意味着我们可以更紧密地遵循单一责任原则(SRP)。

从现在开始,OpenFaaS网关只作为配置选项(如验证、跟踪和度量)的中间件

faas-provider

今天,有一个Golang SDK允许任何人引导OpenFaaS提供者——你只需填写“http.Handler”函数即可,简化了整个体验。

OpenDNS的Alex Boten领导的团队在不到24小时内创建了他们自己的OpenFaaS provider

faas-memory

这是一个 in-memory provider实现的例子。

import (
	bootstrap "github.com/openfaas/faas-provider"
	bootTypes "github.com/openfaas/faas-provider/types"
)

func main() {

	bootstrapHandlers := bootTypes.FaaSHandlers{
		FunctionProxy:  handlers.MakeProxy(),
		DeleteHandler:  handlers.MakeDeleteHandler(),
		DeployHandler:  handlers.MakeDeployHandler(),
		FunctionReader: handlers.MakeFunctionReader(),
		ReplicaReader:  handlers.MakeReplicaReader(),
		ReplicaUpdater: handlers.MakeReplicaUpdater(),
		UpdateHandler:  handlers.MakeUpdateHandler(),
		HealthHandler:  handlers.MakeHealthHandler(),
		InfoHandler:    handlers.MakeInfoHandler(version.BuildVersion(), version.GitCommitSHA),
	}

	readConfig := types.ReadConfig{}
	osEnv := types.OsEnv{}
	cfg := readConfig.Read(osEnv)

	bootstrapConfig := bootTypes.FaaSConfig{
		ReadTimeout:     cfg.ReadTimeout,
		WriteTimeout:    cfg.WriteTimeout,
		TCPPort:         &cfg.Port,
		EnableHealth:    true,
		EnableBasicAuth: false,
	}

	log.Infof("listening on port %d ...", cfg.Port)
	bootstrap.Serve(&bootstrapHandlers, &bootstrapConfig)
}

您可以看到,我们在 bootTypes.FaaSHandlers 中有效地设置了各Handler结构,然后运行 bootstrap.Serve 用于启动provider。

通过遵循provider模型,任何容器编配器或其他系统(如内存存储)都可以作为接入对象,整个OpenFaaS生态系统仍然可用且兼容。

保持兼容

为了保持提供者的兼容性,我们引入了在构建时为Swarm和Kubernetes提供者运行的certifier项目,以确保它们支持API接口。

当Hashicorp的Nic Jackson启动faas-nomad提供程序时,他使用这个工具进行了一种测试驱动的开发。

规则的一个例外:Operator和CRD

2017年,我和Stefan Prodan在KubeCon讨论了将我们的faas-netes改造成一使用自己的Function CRD的Operator。

在Stefan使用来自faas-netes控制器的代码将一个工作操作符组合在一起后不久,它就工作了,这意味着用户可以进行选择。他们可以使用REST API或CRD,实际上他们可以两者都使用。REST API创建了CRD条目。

我们已经有了一个OpenFaaS provider的生态系统和用于不同的容器编制器的 后端,如:Docker Swarm、Kubernetes、AWS Fargate和Hashicorp Nomad。这意味着我们现在有两种正交的方式来在OpenFaaS中部署函数。

所有现有的提供程序都使用stack.yml文件和REST API,但是OpenFaaS Operator现在有了一个CRD。

进入faas-cli generate

我提出了以下建议:特性:通过CLI生成Kubernetes CRD YAML文件

假设我们有一个名为webhook-responder的函数,它接收HTTP消息,然后在Slack中向传入的webhook URL发送消息。

它看起来是下面这样的,由于我们的faas-provider接口,我们可以将它部署到任何兼容的OpenFaaS Provider。

#stack.yml
provider:
  name: openfaas
  gateway: http://127.0.0.1:8080

functions:
  webhook-responder:
    lang: go
    handler: ./webhook-responder
    image: alexellisuk/webhook-responder:latest
    environment:
      write_debug: true
    secrets:
     - webhook-token
     - slack-incoming-url

我们可以使用faas-cli deployfaas-cli up来部署这个函数。

对于Kubernetes的操作人员和开发人员来说,使用REST API提供了一些价值,但是在本质上,我们更喜欢我们最喜欢的工具kubectlkubectl工具允许本地Kubernetes策略和与RBAC和其他工具的深度集成。

我提出的解决方案是创建一个生成命令,它将用一个stack.yml文件作为输入,然后生成一个CRD。下面是它实际的样子:

$ faas-cli generate
# or
$ faas-cli generate --api=openfaas.com/v1alpha2

注意:您可以运行faas-cli generate --help来获得更多的选项。

#webhook-responder.yaml
---
apiVersion: openfaas.com/v1alpha2
kind: Function
metadata:
  name: webhook-responder
  namespace: openfaas-fn
spec:
  name: webhook-responder
  image: alexellisuk/webhook-responder:latest
  environment:
    write_debug: "true"
  secrets:
  - webhook-token
  - slack-incoming-url

这个函数可以用: kubectl apply -f webhook-responder.yaml 来部署。

如果您想了解faas-cli如何生成,那么请查看这里的命令文件:generate.go。最初的版本是由社区的Vivek Syngh编写的。

为Knative扩展faas-cli generate

在2018年夏天,谷歌宣布了一个新的无服务器项目,名为Knative。我立即着手评估这个已经饱和的市场的新进入者,发现用OpenFaaS构建的任何功能都可以部署,而不需要 到他们的平台上修改。

Portability with Knative (gist)

OpenFaaS函数商店允许社区和最终用户共享、发现和协作函数。

在我的Gist,我展示了来自函数存储的函数可以部署到Knative。这启发了Michael Hausenblas, RedHat的开发者倡导者,在他的第一篇Knative博客文章中展示了着色功能 colorise

就在今年KubeCon Barcelona的无服务器从业者峰会(SPS)之前,我开始更新faas-cli以生成Knative服务定义。

Pull request: Add knative serving v1alpha1 to generate CRD command.

$ faas-cli generate --api=serving.knative.dev/v1alpha1

---
apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: webhook-responder
  namespace: openfaas-fn
spec:
  runLatest:
    configuration:
      revisionTemplate:
        spec:
          container:
            image: alexellisuk/webhook-responder:latest
            env:
            - name: write_debug
              value: "true"
            volumeMounts:
            - name: webhook-token
              mountPath: /var/openfaas/secrets/webhook-token
              readOnly: true
            - name: slack-incoming-url
              mountPath: /var/openfaas/secrets/slack-incoming-url
              readOnly: true
          volumes:
          - name: webhook-token
            secret:
              secretName: webhook-token
          - name: slack-incoming-url
            secret:
              secretName: slack-incoming-url

您甚至可以将这个命令传递到kubectl apply,甚至在stack.yml中也可以使用它包含多个函数。

faas-cli generate --api=serving.knative.dev/v1alpha1 | kubectl apply -f -

你可以这样搜索商店:

$ faas-cli store list --verbose
FUNCTION                    DESCRIPTION
Colorization                Turn black and white photos to color ...
Inception                   This is a forked version of the work ...
Have I Been Pwned           The Have I Been Pwned function lets y...
SSL/TLS cert info           Returns SSL/TLS certificate informati...
Face blur by Endre Simo     Blur out faces detected in JPEGs. Inv...
Figlet                      OpenFaaS Figlet image. This repositor...
...

然后将一个函数从商店部署到Knative,例如figlet(生成ASCII标志):

$ faas-cli generate --api=serving.knative.dev/v1alpha1 --from-store="figlet"

包装

OpenFaaS提供者模型及其REST API意味着该项目可以针对各种容器编制器,甚至是AWS Lambda这样的专有SaaS产品,而无需对接口进行任何额外的更改。

faas-cli生成命令还为我们提供了一种方法,可以在不抛弃原始设计的情况下深入集成Kubernetes当前和未来的生态系统。

您可能想知道OpenFaaS REST API和Kubernetes或Knative上OpenFaaS的CRD是否互相正交?这可能是事实,但是OpenFaaS Operator表明我们可以两全其美。

本设计之所以成功,是因为OpenFaaS的目标是Docker或OCI镜像格式和端口8080上的简单HTTP接口。我称之为“Serverless 2.0运行时契约”或“一个Serverless工作负载”。

Serverless 2.0 Landscape

在Serverless 2.0世界中,您可以在任何列出的模板系统中构建函数,然后在选择的任何服务平台和列出的可安装或托管的基础设施产品上运行它们。

我的 其他相关工作:

未来的工作

OpenFaaS的使命是:简化无服务器函数。因此,在我看来,未来的工作是扩展OpenFaaS提供商和CRD生态系统,以便将开发人员的体验带到所有平台。

在2019年,我们的社区将对Kubernetes生态系统的目标进行双重调整:性能、安全性和企业特性。我们也超越了Kubernetes和faas-lambda。Edward Wilde在SPS活动中谈到了他如何创建一个直接部署到AWS Lambda的faas-provider,而不需要对为OpenFaaS构建的图像进行额外的修改。订阅博客获取更多信息。

在我看来,这是社区未来的一些工作:

  • 一个以Knative Serving CRD为接入目标的OpenFaaS provider,它将被(想象地)称为faas-knative,并将OpenFaaS REST API、CLI、函数存储和UI带给Knative用户,以及在无服务器环境下的最佳开发体验之一。
  • Rancher的首席架构师Darren Shepherd表示有兴趣构建一个OpenFaaS Provider,为名为Rio的新Rancher microPaaS平台带来开发者体验。
  • 一个 faas-cli generate --api=services.rio.cattle.io 命令为Rio生成自己的Service定义,以支持实验和快速反馈。看issue

Get involved

我们拥有强大的核心团队和200多名贡献者,现在是参与项目的最佳时机。欢迎贡献和反馈,以及任何其他问题或意见。

不知道如何贡献?加入Slack,然后跟上我们最新的社区视频简报:如何贡献,2019年

Follow @alexellisuk and @openfaas on Twitter.

[翻译]systemd-resolved

URL:https://www.freedesktop.org/software/systemd/man/systemd-resolved.service.html

网络名称解析管理器 systemd-resolved.service

systemd-resolved是一项系统服务,可为本地应用程序提供网络名称解析。它实现了缓存和验证DNS / DNSSEC存根解析器以及LLMNR和MulticastDNS解析器和响应器。本地应用程序可以通过三个接口提交网络名称解析请求:

  1. 系统解析的本机,功能齐全的API 在总线上公开。有关详细信息,请参见 API文档。通常建议客户端使用此API,因为它是异步的且功能齐全(例如,为支持本地链接网络而正确返回DNSSEC验证状态和地址的接口范围)。
  2. RFC3493定义的glibc getaddrinfo(3) API 及其相关的解析程序功能,包括gethostbyname(3)。该API得到了广泛的支持,包括Linux平台之外的其他支持。当前,它不公开DNSSEC验证状态信息,并且仅是同步的。此API由glibc名称服务开关(nss(5))支持。 为了允许glibc的NSS解析器功能通过systemd-resolved解析主机名,需要 使用glibc NSS模块nss-resolve(8)
  3. 此外,systemd-resolved在本地回送接口上的IP地址127.0.0.53上提供了本地DNS存根侦听器。直接绕过任何本地API发出DNS请求的程序可以定向到此存根,以便将它们连接到systemd-resolved。但是请注意,强烈建议本地程序改用glibc NSS或总线API(如上所述),因为各种网络解析概念(例如链接本地寻址或LLMNR Unicode域)无法映射到单播DNS协议。

联系的DNS服务器由以下各项中的全局设置确定: 文件中/etc/systemd/resolved.conf的每个链接静态设置 /etc/systemd/network/*.network(如果使用 systemd-networkd.service(8)),通过DHCP接收的每个链接动态设置,通过resolvectl发出的用户请求 (1),以及其他系统服务可用的任何DNS服务器信息。见 resolved.conf(5)和 systemd.network(5)有关DNS服务器systemd自己的配置文件的详细信息。为了提高兼容性, /etc/resolv.conf为了发现已配置的系统DNS服务器,必须对其进行读取,但前提是它不是指向或的符号链接/run/systemd/resolve/stub-resolv.conf。 /usr/lib/systemd/resolv.conf/run/systemd/resolve/resolv.conf (见下文)。

综合纪录

在以下情况下, systemd解析会合成DNS资源记录(RR):

  • 本地配置的主机名将解析为按其作用域排序的所有本地配置的IP地址,或者-如果未配置,则为IPv4地址127.0.0.2(位于本地环回上)和IPv6地址:: 1(即本地主机)。
  • 主机名“ localhost”和“ localhost.localdomain”(以及任何以“ .localhost”或“ .localhost.localdomain” 结尾的主机名)被解析为IP地址127.0.0.1和:: 1。
  • 主机名“ _gateway”解析为所有当前默认路由网关地址,按其度量标准排序。这将为当前网关分配一个稳定的主机名,对于独立于当前网络配置状态引用该主机名很有用。
  • 在中定义的映射/etc/hosts将解析为其配置的地址并返回,但它们不会影响非地址类型(如MX)的查找。

协议和路由

根据以下规则,查找请求将路由到可用的DNS服务器,LLMNR和MulticastDNS接口:

  • 特殊主机名“ localhost”的查找永远不会路由到网络。(其他一些特殊域的处理方式也相同。)
  • 使用LLMNR协议,将单标签名称路由到所有能够进行IP多播的本地接口。仅通过IPv4上的LLMNR发送对IPv4地址的查找,而仅通过IPv6上的LLMNR发送IPv6地址的查找。本地配置的主机名和“ _gateway”主机名的查找永远不会路由到LLMNR。
  • .local使用MulticastDNS协议,将带有后缀“ ”的多标签名称路由到所有能够进行IP多播的本地接口。与LLMNR一样,IPv4地址查找通过IPv4发送,而IPv6地址查找通过IPv6发送。
  • 其他多标签名称将路由到配置了DNS服务器的所有本地接口,如果存在则将路由到全局配置的DNS服务器。从链接本地地址范围进行的地址查找永远不会路由到DNS。请注意,默认情况下,带有.local后缀“ ”的域的查找不会路由到DNS服务器,除非该域被明确指定为DNS服务器和接口的路由或搜索域。这意味着,在.local站点特定的DNS服务器中定义了“ ”域的网络上,需要配置显式搜索或路由域,以使在此DNS域中的查找有效。请注意,今天通常建议避免.local在DNS服务器中定义“ ”,如RFC6762 保留此域供MulticastDNS专用。

如果将查找路由到多个接口,则返回第一个成功的响应(从而有效地合并所有匹配接口上的查找区域)。如果在所有接口上查找失败,则返回最后一个失败的响应。

查找的路由可能会受到配置每个接口的域名和其他设置的影响。有关详细信息,请参见 systemd.network(5)和 resolvectl(1)。以下查询路由逻辑适用于单播DNS通信:

  • 如果要查找的名称匹配(即:等于或具有后缀)的任何链接的任何已配置搜索或仅路由域(或全局配置的DNS设置),则“最佳匹配”搜索/路由-仅确定域:标签最多的匹配域。然后将查询发送到任何链接的所有DNS服务器或与此“最佳匹配”仅搜索/路由域关联的全局配置的DNS服务器。(请注意,多个链接可能配置了相同的“最佳匹配”搜索/仅路由域,在这种情况下,查询将并行发送给所有它们)。
  • 如果查询与任何已配置的仅搜索/仅路由域(既不是每个链接也不是全局)都不匹配,则它将被发送到在“ DNS默认路由”选项集的链接上配置的所有DNS服务器以及全局配置的DNS服务器。
  • 如果没有将链接配置为“ DNS默认路由”,也没有配置全局DNS服务器,则使用嵌入式后备DNS服务器。
  • 否则,查询将失败,因为无法确定合适的DNS服务器。

“ DNS默认路由”选项是可使用resolvectl或在 .network文件中配置的布尔设置。如果未设置,则根据为链接配置的DNS域隐式确定:如果有任何仅路由域(不匹配“ ~.”),则默认为false,否则为true。

实际上,这意味着:为了将所有未与仅搜索/仅路由域配置明确匹配的DNS查询路由到特定链接,请在其上配置“ ~.仅路由” 域。这将确保不会为查询考虑其他链接(除非它们也带有此类仅路由域)。为了仅在没有其他链接可取的情况下将所有此类DNS查询路由到特定链接,请将该链接的“ DNS默认路由”选项设置为true,并且不要~.在其上配置“ 仅路由” 域。最后,为了确保特定链接永远不会收到与任何其配置的仅搜索/路由域都不匹配的DNS流量,请将其“ DNS默认路由”选项设置为false。

有关API 提供的信息,请参阅已解析的D-Bus API文档systemd-resolved

/etc/resolv.conf

支持四种处理方式/etc/resolv.conf(请参阅 resolv.conf(5)):

  • systemd-resolved维护 /run/systemd/resolve/stub-resolv.conf文件以与传统Linux程序兼容。该文件可能是从链接的/etc/resolv.conf。此文件将127.0.0.53 DNS存根(请参见上文)列出为唯一的DNS服务器。它还包含由systemd-resolved使用的搜索域列表。搜索域列表始终保持最新。请注意, /run/systemd/resolve/stub-resolv.conf应用程序不应直接使用,而只能通过的符号链接使用/etc/resolv.conf/etc/resolv.conf为了连接所有绕过本地DNS API的本地客户 端到具有正确搜索域设置的 systemd-resolved,可以对该文件进行符号链接 。建议使用此操作模式。
  • 提供了一个静态文件/usr/lib/systemd/resolv.conf,该文件列出了127.0.0.53 DNS存根(请参阅上文)作为唯一的DNS服务器。/etc/resolv.conf为了将绕过本地DNS API的所有本地客户端连接到 systemd-resolved,可以对该文件进行符号链接 。该文件不包含任何搜索域。
  • systemd-resolved维护 /run/systemd/resolve/resolv.conf文件以与传统Linux程序兼容。该文件可能是从符号链接的,/etc/resolv.conf并且始终保持最新状态,其中包含有关所有已知DNS服务器的信息。请注意文件格式的局限性:它不了解每接口DNS服务器的概念,因此仅包含系统范围的DNS服务器定义。请注意, /run/systemd/resolve/resolv.conf应用程序不应直接使用,而只能通过的符号链接使用/etc/resolv.conf。如果使用此操作模式,则绕过任何本地DNS API的本地客户端也将绕过 systemd-resolved,并将直接与已知的DNS服务器通信。
  • 或者,/etc/resolv.conf可以由其他程序包管理,在这种情况下,systemd-resolved将读取该数据包以获取DNS配置数据。在这种操作方式下, systemd-resolved是该配置文件的使用者而不是提供者。

请注意,此文件的所选操作模式是完全自动检测到的,具体取决于是否 /etc/resolv.conf将符号链接指向/run/systemd/resolve/resolv.conf127.0.0.53或将其列为DNS服务器。

Signals

SIGUSR1

收到systemd-resolvedSIGUSR1过程信号后, 系统会将其维护的所有DNS资源记录缓存的内容以及它从已配置的DNS服务器中学到的所有功能级别信息都转储到系统日志中。SIGUSR2

收到SIGUSR2过程信号 systemd-resolved后,将刷新其维护的所有缓存。请注意,除调试目的外,通常不需要显式地请求此请求,因为无论何时 主机的网络配置发生更改,systemd-resolved都会自动刷新缓存。发送此信号到systemd-resolved等效于resolvectl flush-caches 命令,但是建议使用后者,因为它以同步方式运行。SIGRTMIN+1

收到SIGRTMIN+1过程信号 systemd-resolved时,将忘记它所了解的有关已配置DNS服务器的所有信息。具体来说,会清除有关服务器功能支持的所有信息,并在下一个请求(从功能最全的级别开始)起重新启动服务器功能探测逻辑。请注意,除调试目的外,通常无需显式请求此请求,因为在DNS服务器配置更改时, systemd-resolved会自动忘记学习的信息。发送此信号到systemd-resolved等效于 resolvectl reset-server-features 命令,但是建议使用后者,因为它以同步方式运行。

天气之子

我觉得比你的名字有更广的内涵,更聚跨语言的感染力。雨,献祭,神明,这是不同具有历史的文化,在渊远的神秘的过去,口耳相传,共有的情感。在科技文明的现在仍能以故事延续。
另外就是价值观,天气与人的幸福是联系在一起的,女主为人类牺牲过,却不为所知,这让知情者凄凉,让我们这些者怅惘。爱能做到的事情,远远不止如此,这也是全剧的高潮。男主的行为,几乎与社会中大人各种规矩背离,疯狂痴情。“我只想再见她一面”,生离死别,嘶吼挣扎。我觉得片中曲“逃离地面”,主题曲“爱能做到的事情”概括就很好。天空中的一幕,场景绝美,被流放到辽阔的无人的天空中,该有多孤独啊。放弃社会,放弃世界,追寻和你在一起。这应该也符合日本在低欲望社会背景下,年轻人对爱情的价值取向吧,义理与人情,摆脱社会意义的约束,追问本心。拯救所爱的人,的确是轰轰烈烈的爱情。结局是美好的,雨女的命运也不见得是悲剧呢[滑稽]。

新海诚的作品情感特点,“孤独”和“离别”。离别的具体表现很多,比如忘记、消失、成长分别、社会约束等等,手法上写实抒情奇幻结合,以现实为根基。再配上极致精致的背景画面。

天气之子中的画面是京阿尼写实的风格,不同于新海诚以前的作品,这是向京阿尼致敬和默哀吧。

京阿尼以真实生活环境取景,在此之上讲述主角的故事,叙事平淡中自有波澜,感情细腻浓郁。

淘票票又给我推荐电影,但是不想点开。电影买单,我觉得就是为情感买单,这一方面看作品的本质特点,一方面看宣传能否激发受众的情感。感情共鸣也受受众的文化、社会环境、价值取向影响。

动画的想象力表现力买单。

Handle与Handler

handle 句柄

第一种解释:句柄是一种特殊的智能指针 。当一个应用程序要引用其他系统(如数据库、操作系统)所管理的内存块或对象时,就要使用句柄。

第二种解释:整个Windows编程的基础。一个句柄是指使用的一个唯一的整数值,即一个4字节(64位程序中为8字节)长的数值,来标识应用程序中的不同对象和同类中的不同的实例

Handler 处理器

用于异步消息的处理:当发出一个消息之后,首先进入一个消息队列,发送消息的函数即刻返回,而另外一个部分在消息队列中逐一将消息取出,然后对消息进行处理,也就是发送消息和接收消息不是同步的处理。 这种机制通常用来处理相对耗时比较长的操作。

[推荐]网络加速器

推荐两个一直在用的网络加速器:

1. 一枝红杏

用了四年,也被墙过,但一直更新。比一些续了一年就挂了靠谱多了。双十二有7折优惠(入门级套餐年付7折后69元,每月50G,11个节点)。 是个小而美的SS加速器 。

支持续费, 账号续费的形式。

试用活动下架了。邀请链接

2. 布丁

最近看到有活动,5折(最低的年付套餐5折后 44元,每月128G,12个节点),测试速度不错,是个小而美的V2ray加速器。

每月更新订阅的形式。流量包套餐的形式。

感兴趣的还有1元的试用套餐,试用好像快下架了。邀请链接

GOPROXY环境变量

从 Go 1.11 版本开始,官方支持了 go module 包依赖管理工具,也新增了 GOPROXY 环境变量。如果设置了该变量,下载源代码时将会通过这个环境变量设置的代理地址,而不再是以前的直接从代码库下载。

公用的代理服务 https://goproxy.io,go 1.13镜像地址改为 https://proxy.golang.org,direct 了。
需要依赖于 go module 功能。可通过 export GO111MODULE=on 开启 MODULE。

export GO111MODULE=on
export GOPROXY=https://goproxy.io

使用 go module 包依赖管理工具 ,go build前确认配置好了上述环境变量,会很方便。

当然可以指定自己的代理

GOPROXY=socks5://127.0.0.1:2333

补充:GO Module学习文档

常用命令:

go mod edit -go=1.13

实不相瞒,我觉得golang的依赖管理真是差劲,对初学者一点都不友好。接手一个项目,依赖时常搞不定。

错误1

go: github.com/hashicorp/gopsutil@v0.0.0-20180427102116-62d5761ddb7d: invalid pseudo-version: does not match version-control timestamp (2019-01-17T15:36:06Z)

格式为v0.0.0-20180427102116-62d5761ddb7d的版本号表示git存储库中没有标记的版本。所以go mod根据git最新的提交时间和SHA-1提交哈希的12位前缀生成一个。

补充伪版本版本校验的概念 。
1) a "pseudo-version" like v0.0.0-yyyymmddhhmmss-abcdefabcdef
2) There are three pseudo-version forms.
3) 如果主模块中的require指令使用了无效的伪版本,通常可以通过将版本编辑为仅提交哈希值并重新运行go命令(例如go list -m allgo mod tidy)来进行更正。
4) 如果主模块的传递依赖项之一要求使用无效版本或伪版本,则可以使用主模块go.mod文件中的replace指令将无效版本替换为有效版本。如果替换是提交哈希,它将被解析为上述适当的伪版本。
5) 如何在go.mod文件中生成所有依赖的模块

错误2

go: github.com/hashicorp/go-msgpack@v0.5.5 used for two different module paths (github.com/hashicorp/go-msgpack and github.com/ugorji/go)

不清楚项目依赖关系,多了就删吧。或者把两个出线的地方版本换成不一样的。

go: finding xxxxx
go: downloading xxxxxx
go: extracting xxxxxx
包在pkg/mod/目录下

补充:go module升级或降级依赖