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

Stella981
• 阅读 383

墨迹一点

个人琐碎

最近比较忙,以致于很久都没有写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)

点赞
收藏
评论区
推荐文章
光头强的博客 光头强的博客
4个月前
Java面向对象试题
1、请创建一个Animal动物类,要求有方法eat()方法,方法输出一条语句“吃东西”。创建一个接口A,接口里有一个抽象方法fly()。创建一个Bird类继承Animal类并实现接口A里的方法输出一条有语句“鸟儿飞翔”,重写eat()方法输出一条语句“鸟儿吃虫”。在Test类中向上转型创建b对象,调用eat方法。然后向下转型调用eat()方
刚刚好 刚刚好
4个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
blmius blmius
1年前
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
晴空闲云 晴空闲云
4个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
3个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
Stella981 Stella981
1年前
Gevent简明教程
1、前述进程线程协程异步并发编程(不是并行)目前有四种方式:多进程、多线程、协程和异步。多进程编程在python中有类似C的os.fork,更高层封装的有multiprocessing标准库多线程编程python中有Thread和threading异步编程在linux下主要有三种实现selec
Stella981 Stella981
1年前
Goroutine(协程)为何能处理大并发?
简单来说:协程十分轻量,可以在一个进程中执行有数以十万计的协程,依旧保持高性能。进程、线程、协程的关系和区别:进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调度。线程拥有自己独立的栈和共享的堆,共享堆,不共享栈,线程亦由操作系统调度(标准线程是的)。协程和线程一样共享堆
Wesley13 Wesley13
1年前
Go 并发
Go并发并发指的是同时处理多个任务的能力。并行指的是并行处理多个任务的能力。并行不一定加快运行速度,因为并行组件之间可能需要互相通信。Go中使用协程,信道来处理并发。协程Go中主要通过协程实现并发。协程是与其他函数或方法一起并发运行的函数或方法,协程可以看作是轻量级线程,但是创建成本更小,我们经常
Easter79 Easter79
1年前
Swoole2.0内置协程并发测试
Swoole2.0是一个革命性的版本,它内置了协程的支持。与Go语言协程不同,Swoole协程完全不需要开发者添加任何额外的关键词,直接以过去最传统的同步阻塞模式编写代码,底层自动进行协程调度实现异步IO。使并发编程变得非常简单。最新的版本中,内置协程已支持PHP7,同时兼具了性能和并发能力,Swoole的强大超乎想象。本文基于Github最新的Sw
helloworld_28799839 helloworld_28799839
4个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue