Go实现FastCgi Proxy Client 系列(三)优化篇

墨迹一点

个人琐碎

最近比较忙,以致于很久都没有写blog了,但是,golang的水平自认为是总算入门了。

协程的个人理解

网上的说法一般都是协程是轻量级线程。

我个人认为协程的好处

  1. 无需在用户态和内核态切换(完全在用户态)
  2. 无需线程上下文切换的开销(因为之上的好处)
  3. 编码简单(原子操作,锁都没有了)

httpHandler优化

利用协程优化请求

这是我们原本的handler(就是监听http请求的一个对象,实现了ServeHTTP)

1type HttpHandler struct 2{ 3 Vhosts Vhosts 4 HandlerMap map[string]*http.ServeMux 5}

很明显,这里就已经是入口了,我们将其修改成

1type HttpHandler struct 2{ 3 Vhosts Vhosts 4 HandlerMap map[string]*http.ServeMux 5 Response chan *Response 6 StaticFile chan *StaticFileHandler 7 serverEnvironment map[string]string 8}

当我们遇到请求的实行,我们直接开启协程

go Run(w,r)

在Run方法中,将实现部分写入协程(即IO、计算部分),在大部分代码不变的情况下(请看1和2的分析)我们将几种错误的情况抛出一个Response对象,比如请求的是/favicon.ico

1if r.RequestURI == "/favicon.ico" { 2 httpHandler.Response <- &Response{200, map[string]string{}, nil, ""} 3 return 4}

具体的伪代码应如下:

1if something wrong { 2 gerWrongCode 3 res := generate WrongResponse 4 httpHandler.Response <- res 5 return 6} 7 8 9res := do proxy 10httpHandler.Response <- res

另外,关于静态文件,我们并不需要proxy,所以我们要告知上面,这个是静态文件,go直接处理

1 fileCode,filename := httpHandler.buildServerHttp(r, env, hm) 2 3 switch fileCode { 4 case FileCodeStatic: 5 httpHandler.StaticFile <- &StaticFileHandler{ 6 name, 7 port, 8 filename, 9 } 10 return 11 case ...... 12 }

处理协程回调

那么确定我们已经将各种IO和逻辑处理写入了协程了,这个时候,我们回到ServeHTTP方法

1 go Run(w,r) 2 for { 3 select { //进行协程的处理 4 case response := <-httpHandler.Response: //当遇到response的时候 送出结果 5 response.send(w, r) 6 case hand := <-httpHandler.StaticFile: //当遇到是静态文件的时候 直接走本身go原本的handler 7 staticHandler := httpHandler.HandlerMap[hand.Host+hand.Port] 8 staticHandler.ServeHTTP(w, r) 9 10 default: 11 respond(w, "<h1>404</h1>", 404, map[string]string{}) 12 } 13 }

添加日志

像nginx之类的,都可以写日志,那这个功能我也不能少

只需要在HttpHandler对象注入的时候加入一个log即可

1type HttpHandler struct 2{ 3 Vhosts Vhosts 4 HandlerMap map[string]*http.ServeMux 5 Response chan *Response 6 StaticFile chan *StaticFileHandler 7 serverEnvironment map[string]string 8 log *log.Logger 9} 10 11func (httpHandler *HttpHandler) SetLogger(log *log.Logger) { 12 httpHandler.log = log 13} 14 15func (httpHandler *HttpHandler) GetLogger() *log.Logger { 16 return httpHandler.log 17}

然后,代码中可以放心大胆的使用 log.*方法

至于log写文件 ,百度谷歌谢谢,他本身就带了异步IO,就不用操心了。

其他

本文源码

Go实现FastCgi Proxy Client 系列(一)

Go实现FastCgi Proxy Client 系列(二)

一个FCM的消息代理服务器

一个秒级定时任务(非crontab)

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

Kotlin 协程中,关于 runBlocking, launch ,withContext ,async,doAsync 之间的简单区别

引入大佬的话,Kotlin的协程,本质上是一个线程框架,它可以方便的切换线程的上下文(如主线程切换到子线程/子线程切回主线程)。而平时我们要想在AndroidStudio使用协程,先要在gradle引入协程依赖:implementation"org.jetbrains.kotlinx:kotlinxcoroutinescore:1.3.3"

GO语言协程的理解

以下内容大部分摘自许世伟的《GO语言核心编程》最近面试,在自己的简历上写了简单会一些GO语言。结果被面试官问了GO语言goroutine的原理。自己看倒是看过,时间长了又给忘了。特此写下此文以长记性。协程:协程本质上是一种用户态线程,不需要操作系统来进行抢占式调度,并且在真正的实现中寄存于线程中,因此系统开销极小,可以有效的提高线程任务的并发性,而避

Goroutine(协程)为何能处理大并发?

简单来说:协程十分轻量,可以在一个进程中执行有数以十万计的协程,依旧保持高性能。进程、线程、协程的关系和区别:进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。协程和线程一样共享堆