暂且放下你的编程语言来瞻仰下我所见过的最棒的标准库。
为项目选择编程语言和挑选你最爱的球队不一样。应该从实用主义出发,根据特定的工作选择合适的工具。
在这篇文章中我会告诉你从何时开始并且为什么我认为去语言如此闪耀,具体来说是它的标准库对于基本的网络编程来说显得非常稳固。更具体一点,我们将要编写一个反向代理程序。
去为此提供了很多,但真正支撑起它的在于这些低级的网络管道任务,没有更好的语言了。
反向代理是什么? <强>有个很棒的说法是流量转发>强。我获取到客户端来的请求,将它发往另一个服务器,从服务器获取到响应再回给原先的客户端。反向的意义简单来说在于这个代理自身决定了何时将流量发往何处。
为什么这很有用?因为反向代理的概念是如此简单以至于它可以被应用于许多不同的场景:负载均衡,A/B测试,高速缓存,验证等等。
当读完这篇文章之后,你会学到:
-
<李>如何响应HTTP请求李>
<李>,如何解析请求体李>
<李>如何通过反向代理将流量转发到另一台服务器李>
, <强>我们的反向代理项目强>
我们来实际写一下项目。我们需要一个Web服务器能够提供以下功能:
-
<李>获取到请求李>
<李>读取请求体,特别是proxy_condition字段李>
<李>如果代理域为,则转发到URL 1 李>
<李>如果代理域为B,则转发到URL 2 李>
<李>如果代理域都不是以上,则转发到默认的URL李>
<强>准备工作强>
-
<李>,去语言环境。李>
<李> http服务器用来创建简单的服务。李>
<强>环境配置强>
我们要做的第一件事是将我们的配置信息写入环境变量,如此就可以使用它们而不必写死在我们的源代码中。
我发现最好的方式是创建一个包含所需环境变量的<代码>。env 代码>文件。
以下就是我为特定项目编写的文件内容:
出口港口=1330 出口A_CONDITION_URL=" http://localhost: 1331 " 出口B_CONDITION_URL=" http://localhost: 1332 " 出口DEFAULT_CONDITION_URL=http://localhost: 1333
这是我从12个因素应用项目中获得的技巧。
保存完<代码>。env 代码>文件之后就可以运行:
源.env
在任何时候都可以运行该指令来将配置加载进环境变量。
<强>项目基础工作强>
接着我们创建<代码>主要。代码>文件做如下事情:
-
<李>将<代码>口代码>,<代码> A_CONDITION_URL 代码>,<代码> B_CONDITION_URL 代码>和<代码> DEFAULT_CONDITION_URL> 代码变量通过日志打印到控制台。李>
<李>在<代码>/代码>路径上监听请求:李>
主要包 导入( “字节” “编码/json” “io/ioutil” “日志” "net/http” "net/http/httputil” "net/url” “操作系统” “弦” )//env var或违约 {func getEnv(钥匙,后退字符串)字符串 如果价值,好的:=os.LookupEnv(关键);好{ 返回值 } 返回回退 }//获取端口听> requestPayloadStruct struct类型{ ProxyCondition字符串的json:“proxy_condition” }//得到一个json解码器的身体对于一个给定的请求 func requestBodyDecoder(请求* http.Request) * json。解码器{//读取缓冲区 身体,犯错:=ioutil.ReadAll (request.Body) 如果犯错!=nil { 日志。Printf(“错误阅读身体:% v”,呃) 恐慌(err) }//因为去朗是一个眼中钉如果你读然后身体任何susequent调用//无法阅读的身体再次.... 请求。身体=ioutil.NopCloser (bytes.NewBuffer(身体)) 返回json.NewDecoder (ioutil.NopCloser (bytes.NewBuffer(身体))) }//解析请求的身体 func parseRequestBody(请求* http.Request) requestPayloadStruct { 解码器:=requestBodyDecoder(请求) var requestPayload requestPayloadStruct 错:=decoder.Decode(和requestPayload) 如果犯错!=nil { 恐慌(err) } 返回requestPayload }//给定一个请求发送到适当的url func handleRequestAndRedirect (res http。ResponseWriter点播* http.Request) { requestPayload:=parseRequestBody(要求)//嗟睦? }1行去代码实现反向代理的示例