为了账号安全,请及时绑定邮箱和手机立即绑定

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

标签:
Go

摘要: 都知道golang是天然的适合高并发开发,但是我们之前的代码似乎没有任何用到golang性能的地方。

                                   

墨迹一点

个人琐碎

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

协程的个人理解

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

我个人认为协程的好处

  1. 无需在用户态和内核态切换(完全在用户态)

  2. 无需线程上下文切换的开销(因为之上的好处)

  3. 编码简单(原子操作,锁都没有了)

httpHandler优化

利用协程优化请求

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

type HttpHandler struct{   
    Vhosts     Vhosts
    HandlerMap map[string]*http.ServeMux
}

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

type HttpHandler struct{   
    Vhosts            Vhosts
    HandlerMap        map[string]*http.ServeMux
    Response          chan *Response
    StaticFile        chan *StaticFileHandler
    serverEnvironment map[string]string}

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

go Run(w,r)

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

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

具体的伪代码应如下:

if something wrong { 
    gerWrongCode 
    res := generate WrongResponse
    httpHandler.Response <- res    return }res := do proxy
httpHandler.Response <- res

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

        fileCode,filename := httpHandler.buildServerHttp(r, env, hm)		switch fileCode {		case FileCodeStatic:
			httpHandler.StaticFile <- &StaticFileHandler{
				name,
				port,
				filename,
			}			return
            case ......
        }

处理协程回调

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

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

添加日志

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

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

type HttpHandler struct{   
	Vhosts            Vhosts
	HandlerMap        map[string]*http.ServeMux
	Response          chan *Response
	StaticFile        chan *StaticFileHandler
	serverEnvironment map[string]string
	log               *log.Logger
}func (httpHandler *HttpHandler) SetLogger(log *log.Logger) {
	httpHandler.log = log
}func (httpHandler *HttpHandler)  GetLogger() *log.Logger {	return httpHandler.log
}

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

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

其他

本文源码

Go实现FastCgi Proxy Client 系列(一)

Go实现FastCgi Proxy Client 系列(二)

一个FCM的消息代理服务器

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

作者:o0无忧亦无怖                    

来源:https://my.oschina.net/lwl1989/blog/1813102


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消