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

Python011

go语言实现一个简单的简单网关,第1张

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

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

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

整理:go语言钟文文档:www.topgoer.cn

启动两个后端 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 计数;一种是链式调用。

具体代码

1、反射可以在运行时 动态获取变量的各种信息 ,比如变量的类型、类别;

2、如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段、方法);

3、通过反射,可以修改 变量的值 ,可以调用关联的方法;

4、使用反射,需要import " reflect ".

5、示意图:

1、不知道接口调用哪个函数,根据传入参数在运行时确定调用的具体接口,这种需要对函数或方法反射。

例如以下这种桥接模式:

示例第一个参数funcPtr以接口的形式传入函数指针,函数参数args以可变参数的形式传入,bridge函数中可以用反射来动态执行funcPtr函数。

1、reflect.TypeOf(变量名),获取变量的类型,返回reflect.Type类型。

2、reflect.ValueOf(变量名),获取变量的值,返回reflect.Value类型reflect.Value是一个结构体类型。

3、变量、interface{}和reflect.Value是可以互相转换的,这点在实际开发中,会经常使用到。

1、reflect.Value.Kind,获取变量的 类别(Kind) ,返回的是一个 常量 。在go语言文档中:

示例如下所示:

输出如下:

Kind的范畴要比Type大。比如有Student和Consumer两个结构体,他们的 Type 分别是 Student 和 Consumer ,但是它们的 Kind 都是 struct 。

2、Type是类型,Kind是类别,Type和Kind可能是相同的,也可能是不同的。

3、通过反射可以在让 变量 在 interface{} 和 Reflect.Value 之间相互转换,这点在前面画过示意图。

4、使用反射的方式来获取变量的值(并返回对应的类型),要求数据类型匹配,比如x是int,那么久应该使用reflect.Value(x).Int(),而不能使用其它的,否则报panic。

如果是x是float类型的话,也是要用reflect.Value(x).Float()。但是如果是struct类型的话,由于type并不确定,所以没有相应的方法,只能 断言。

5、通过反射的来修改变量,注意当使用SetXxx方法来设置需要通过对应的指针类型来完成,这样才能改变传入的变量的值,同时需要使用到reflect.Value.Elem()方法。

输出num=20,即成功使用反射来修改传进来变量的值。

6、reflect.Value.Elem()应该如何理解?

LiteIDE是一款专门为Go语言开发的跨平台轻量级集成开发环境(IDE),由QT编写。

LiteIDE主要特点: 支持主流操作系统

Windows

Linux

MacOS X Go编译环境管理和切换

管理和切换多个Go编译环境

支持Go语言交叉编译 与Go标准一致的项目管理方式

基于GOPATH的包浏览器

基于GOPATH的编译系统

基于GOPATH的Api文档检索 Go语言的编辑支持

类浏览器和大纲显示

Gocode(代码自动完成工具)的完美支持

Go语言文档查看和Api快速检索

代码表达式信息显示F1

源代码定义跳转支持F2

Gdb断点和调试支持

gofmt自动格式化支持 其他特征

支持多国语言界面显示

完全插件体系结构

支持编辑器配色方案

基于Kate的语法显示支持

基于全文的单词自动完成

支持键盘快捷键绑定方案

Markdown文档编辑支持

实时预览和同步显示

自定义CSS显示

可导出HTML和PDF文档

批量转换/合并为HTML/PDF文档 Sublime Text 2(以下简称Sublime)+ GoSublime + gocode + MarGo的组合。

其优点有: 自动化提示代码。 保存的时候自动格式化代码,让您编写的代码更加美观,符合Go的标准。 支持项目管理 支持语法高亮熟悉Java的读者应该对于idea不陌生,idea是通过一个插件来支持go语言的高亮语法,代码提示和重构实现。