一般我们用Golang原生写Web时,一般这样写
如果需要特定的GET,POST,PUT,DELETE处理. 我们需要这样写.
对以上方法操作进行了封装.
不过最后还是推荐使用httprouter, 大名顶顶的Gin Web框架就是使用这个的. 自己写的,纯属学习.
大多数现代Web组件栈允许通过栈式/组件式中间件"过滤"请求,这样就能干净地从web应用中分离出横切关注点(译注:面向方面程序设计中的概念?). 本周我尝试在Go语言的 http.FileServer 中植入钩子,发现实现起来十分简便,让我非常惊讶.
让我们从一个基本的文件服务器开始说起:
func main() {
}
我们在mian函数中,首先初始化配置文件,然后新建http连接.
这个方法中首先我们创建一个websocket的Upgrader实例,然后我们使用Upgrader的upgrade方法来升级一下我们的连接为长连接.
升级完成之后会返回一个*websocket.Conn的连接,我们之后所有的关于连接的操作,都是基于该conn的.
在该连接完成之后,我们将连接存放到一个名为Client的map中,以便之后管理更为方便.
之后,我们启动一个goroutine来读取连接中发送的信息内容,再根据内容进行相应的操作.
网关=反向代理+负载均衡+各种策略,技术实现也有多种多样,有基于 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 传入即可.
随便 random 一个整数作为索引,然后取对应的地址即可,实现比较简单.
使用curIndex进行累加计数,一旦超过 rss 数组的长度,则重置.
后端真实节点包含三个权重:
操作步骤:
一致性 hash 算法,主要是用于分布式 cache 热点/命中问题;这里用于基于某 key 的 hash 值,路由到固定后端,但是只能是基本满足流量绑定,一旦后端目标节点故障,会自动平移到环上最近的那么个节点.
实现:
每一种不同的负载均衡算法,只需要实现添加以及获取的接口即可.
然后使用工厂方法,根据传入的参数,决定使用哪种负载均衡策略.
作为网关,中间件必不可少,这类包括请求响应的模式,一般称作洋葱模式,每一层都是中间件,一层层进去,然后一层层出来.
中间件的实现一般有两种,一种是使用数组,然后配合 index 计数;一种是链式调用.
相比于Java的HTTPServer开发基本上都是使用Spring或者Springboot框架,总是要配置各种配置类,各种 handle 对象.Golang的Server开发显得非常简单,就是因为特别简单,或者说没有形成特别统一的规范或者框架,我发现了很多实现方式,HTTP协议基于还是 net/http 和 fasthttp ,但是 handle 语法就多种多样了.
在Golang语言方面,实现某个功能的库可能会比较多,有机会还是要多跟同行交流,指不定就发现了更好用的库.下面我分享我学到的六种Server开发的实现Demo.
基于 net/http 实现,这是一种比较基础的,对于接口和 handle 映射关系处理并不优雅,不推荐使用.
第二种也是基于 net/http ,这种编写语法可以很好地解决第一种的问题,handle和path有了类似配置的语法,可读性提高了很多.
第三个基于 net/http 和 github.com/labstack/echo ,后者主要提供了 Echo 对象用来处理各类配置包括接口和handle映射,功能很丰富,可读性最佳.
第四种依然基于 net/http 实现,引入了 github.com/gin-gonic/gin 的路由,看起来接口和 handle 映射关系比较明晰了.
第五种基于 fasthttp 开发,使用都是 fasthttp 提供的API,可读性尚可,handle配置倒是更像Java了.
第六种依然基于 fasthttp ,用到了 github.com/buaazp/fasthttprouter ,有点奇怪两个居然不在一个GitHub仓库里.使用语法跟第三种方式有点类似,比较有条理,有利于阅读.
在做测试的时候,需要模拟HTTP server的handle函数直接调用:
就不用通过发送curl命令,而是直接调用handler函数的方式;这样就需要手动构造出一个http.ResponseWriter和http.Request,然后调用Handler函数.
好在golang自带的"net/http/httptest"包就有这个功能:
如果使用"github.com/gorilla/mux"的router包想使用Vars可以这么设置:
然后在Handler函数里,就能使用: