go语言实现一个简单的简单网关

网关=反向代理+负载均衡+各种策略,技术实现也有多种多样,有基于 nginx 使用 lua 的实现,比如 openresty、kong;也有基于 zuul 的通用网关;还有就是 golang 的网关,比如 tyk。

这篇文章主要是讲如何基于 golang 实现一个简单的网关。

转自: troy.wang/docs/golang/posts/golang-gateway/

整理:go语言钟文文档:

启动两个后端 web 服务(代码)

这里使用命令行工具进行测试

具体代码

直接使用基础库 httputil 提供的NewSingleHostReverseProxy即可,返回的reverseProxy对象实现了serveHttp方法,因此可以直接作为 handler。

具体代码

director中定义回调函数,入参为*http.Request,决定如何构造向后端的请求,比如 host 是否向后传递,是否进行 url 重写,对于 header 的处理,后端 target 的选择等,都可以在这里完成。

director在这里具体做了:

modifyResponse中定义回调函数,入参为*http.Response,用于修改响应的信息,比如响应的 Body,响应的 Header 等信息。

最终依旧是返回一个ReverseProxy,然后将这个对象作为 handler 传入即可。

参考 2.2 中的NewSingleHostReverseProxy,只需要实现一个类似的、支持多 targets 的方法即可,具体实现见后面。

作为一个网关服务,在上面 2.3 的基础上,需要支持必要的负载均衡策略,比如:

随便 random 一个整数作为索引,然后取对应的地址即可,实现比较简单。

具体代码

使用curIndex进行累加计数,一旦超过 rss 数组的长度,则重置。

具体代码

轮询带权重,如果使用计数递减的方式,如果权重是5,1,1那么后端 rs 依次为a,a,a,a,a,b,c,a,a,a,a…,其中 a 后端会瞬间压力过大;参考 nginx 内部的加权轮询,或者应该称之为平滑加权轮询,思路是:

后端真实节点包含三个权重:

操作步骤:

具体代码

一致性 hash 算法,主要是用于分布式 cache 热点/命中问题;这里用于基于某 key 的 hash 值,路由到固定后端,但是只能是基本满足流量绑定,一旦后端目标节点故障,会自动平移到环上最近的那么个节点。

实现:

具体代码

每一种不同的负载均衡算法,只需要实现添加以及获取的接口即可。

然后使用工厂方法,根据传入的参数,决定使用哪种负载均衡策略。

具体代码

作为网关,中间件必不可少,这类包括请求响应的模式,一般称作洋葱模式,每一层都是中间件,一层层进去,然后一层层出来。

中间件的实现一般有两种,一种是使用数组,然后配合 index 计数;一种是链式调用。

具体代码

Go语言os标准库常用方法Getwd/Getenv/Chdir

1. os.Getwd()函数

原型:func Getwd()(pwd string, err error)

作用:获取当前文件路径

返回:当前文件路径的字符串和一个err信息

示例:

输出:

当前路径: D:ProjectsGomGoLab01

2. os.Getenv()函数

原型:func Getenv(key string) string

作用:获取系统环境变量的值

参数:key - 系统环境变量名

返回:系统环境变量的值

示例:

输出:

环境变量GOPATH的值是: D:/Projects/Go

3. os.Chdir()函数

原型:func Chdir(dir string) error

作用:将当前文件路径改变为目标路径(非真实改变)

参数:dir - 目标路径(即改变之后的路径)

返回:修改成功,返回 nil;修改失败(如:目标路径不存在的情况),返回错误信息。

示例一:

输出:

起始路径: D:ProjectsGomGoLab01

修改后的路径: D:ProjectsGoDemo02

示例二:

输出:

起始路径: D:ProjectsGomGoLab01

error: chdir D:ProjectsGoDemo03: The system cannot find the file specified.

注:文件路径,Window 系统下默认是“”,写在代码中时要用“”或“/”代替。

golang命令行库Cobra的使用

写了2次才写完,内容很长,翻译了很久,内容来源于Cobra github介绍。翻译完也更全面的了解了Cobra,功能相当强大完善,各种使用的场景都考虑到了。另外也扩展了一些其它知识,比如 命令行玩法 , Levenshtein distance 等等。以下是正文:

Cobra提供简单的接口来创建强大的现代化CLI接口,比如git与go工具。Cobra同时也是一个程序, 用于创建CLI程序

Cobra是建立在结构的命令、参数和标志之上。

命令代表操作,参数和标志是这些行动的修饰符。

最好的应用程序就像读取句子。用户会知道如何使用本机应用程序,因为他们将理解如何使用它。

比如下面的例子, server 是命令, port 是标志:

在下面的命令,我们告诉Git克隆url地址bare

使用Cobra很简单。首先,使用 go get 安装最新版本

然后在你项目里引用Cobra

通常基于Cobra的应用程序将遵循下面的组织结构,当然你也可以遵循自己的接口:

在Cobra应用程序中,通常main.go文件非常空洞。它主要只干一件事:初始化Cobra。

Cobra提供自己的程序来创建你的程序并且添加你想要的命令。这是最简单的方式把Cobra添加到你的程序里。

这里 你能找到相关信息

使用Cobra,需要创建一个空的main.go文件和一个rootCmd文件。你可以选择在合适的地方添加额外的命令。

Cobra不需要特殊的构造函数。简单的就可以创建你的命令。

理想情况下你把这个放在在 app/cmd/root.go

你会另外定义标志和处理配置init()函数。

比如 cmd/root.go

你需要在main函数里执行root命令。

通常main.go文件非常空洞。它主要只干一件事:初始化Cobra。

其它的命令通常定义在cmd/目录下的自己文件内

如果你想创建一个version命令,你可以创建cmd/version.go文件,并在文件里这么写:

标志提供修饰符控制动作命令如何操作

当标志定义好了,我们需要定义一个变量来关联标志

'持久'表示每个在那个命令下的命令都将能分配到这个标志。对于全局标志,'持久'的标志绑定在root上。

Cobra默认只在目标命令上解析标志,父命令忽略任何局部标志。通过打开 Command.TraverseChildren Cobra将会在执行任意目标命令前解析标志

你同样可以通过 viper 绑定标志:

在这个例子中,永久的标记 author 被 viper 绑定, 注意 , 当用户没有给 --author 提供值, author 不会被赋值。

标记默认是可选的,如果你希望当一个标记没有设置时,命令行报错,你可以标记它为必须的

验证位置参数可以通过 Command 的 Args 字段。

内置下列验证方法

一个设置自定义验证的例子

在下面的例子,我们定义了3个命令。2个在顶级,一个(cmdTimes)是其中一个顶级命令的子命令。在这个例子里,由于没有给 rootCmd 提供 Run ,单独的root是不能运行的,必须要有子命令。

我们仅为一个命令定义了标记。

更多关于flags的文档可以在 找到

更完整大型程序的例子, 可以查看 Hugo .

当你的程序有子命令时,Cobra 会自动给你程序添加help命令。当你运行‘app help’,会调用help命令。另外,help同样支持其它输入命令。例如,你有一个没有任何其它配置的命令叫‘create’,当你调用‘app help create’ Corbra 将会起作用。

下面的输入是 Cobra 自动生成的。除了命令和标志的定义,其它不再需要。

help 就跟其它命令一样,并没有特殊的逻辑或行为。事实上,你也可以提供你自己help如果你想的话。

你能为默认的命令,提供你自己的help命令或模板。使用下面的方法:

后2个也将适用于任何子命令

当用户提供无效的标记或命令,Cobra 将会返回 用法 。

你可能从上面的帮助意识到,默认的帮助将被嵌入到用法里然后作为输出。

你能提供你自己的用法函数或模板给 Cobra 使用。

比如帮助,方法和模板都可以重写。

如果Version字段设置到了根命令,Cobra 会提供了一个顶层 ‘--version’标记。运行带上‘--version’标记的程序,将会按照模板版本信息。模板可以通过 cmd.SetVersionTemplate(s string) 方法修改

在命令运行前或运行后,再运行方法非常容易。 PersistentPreRun 和 PreRun 方法将会在 Run 之前执行。 PersistentPostRun 和 PostRun 方法将会在 Run 之后执行。 Persistent*Run 方法会被子命令继承,如果它们自己没有定义的话。这些方法将按照下面的属性执行:

下面的例子,2个命令都使用了上面的特性。当子命令执行的时候,它将执行根命令的 PersistentPreRun ,但不会执行根命令的 PersistentPostRun :

输出:

Cobra 会自动输出建议,当遇到“unknown command”错误时。这使得当输入错误时, Cobra 的行为类似 git 命令。例如:

建议会基于注册的子命令自动生成。使用了 Levenshtein distance 的实现。每一个注册的命令会匹配2个距离(忽略大小写)来提供建议。

如果你希望在你的命令里,禁用建议或虚弱字符串的距离,使用:

你可以通过 SuggestFor 来给命令提供明确的名词建议。这个特性允许当字符串不相近,但是意思与你的命令相近,别切你也不想给该命令设置别名。比如:

Cobra 可以基于子命令,标记,等生成文档。以以下格式:

Cobra 可以生成一个bash-completion文件。如果你给命令添加更多信息,这些completions可以非常强大和灵活。更多介绍在 Bash Completions 。

awesome-go:很全的go语言资源合集

awesome-go :一个很全的go语言框架,库,软件合集

前面发过关于awsone-python, awsone django, flask。最近在学习golang,所以找到awsone-go

由于内容太多,这里只是列出主要的目录,每一项下面又有很多内容。具体详细的内容,请到官网查看。

github网址 ,

官网 。

如何用golang 读取xlsx文件

就一段代码也没有源文件也不告诉err原文是啥怎么给你调啊。

最简单的方法就是打开excel转换成xlsx再读。