专栏电商日志财经减肥爱情
投稿投诉
爱情常识
搭配分娩
减肥两性
孕期塑形
财经教案
论文美文
日志体育
养生学堂
电商科学
头戴业界
专栏星座
用品音乐

一文读懂GoHttpServer原理

  hello大家好呀,我是小楼,这是系列文《Go底层原理剖析》的第二篇,依旧是分析Http模块,话不多说,开始。
  从一个Demo入手
  俗话说万事开头难,但用Go实现一个HttpServer真不难,简单到什么程度?起一个Server,并且能响应请求,算上包名、导入的依赖,甚至空行,也就只要15行代码:packagemainimport(ionethttp)funcmain(){http。HandleFunc(hello,hello)http。ListenAndServe(:81,nil)}funchello(responsehttp。ResponseWriter,requesthttp。Request){io。WriteString(response,helloworld)}
  这么简单,能与之一战的恐怕只有Python了吧,而且Go还能编译成可执行的二进制文件,你说牛啤不牛啤?
  HttpServer如何处理连接?
  我们从这一行代码看起http。ListenAndServe(:81,nil)
  从命名来看,这个方法干了两件事,监听并且服务,从方法的单一职责上来说,我觉得不ok,一个方法怎么能干两件事?但这是大佬写的代码,就很合理。
  第一个参数Addr是要监听的地址和端口,第二个参数Handler一般是nil,它是真正的逻辑处理,但我们通常用第一行代码那样来注册处理器,这代码一看就感觉是把path映射到业务逻辑上,我们先大概了解,待会再来看它http。HandleFunc(hello,hello)
  如果了解过一点网络编程基础,就会知道操作系统提供了bind、listen、accept这样的系统调用,我们只要按顺序发起调用,就能组合出一个Server。
  Go也是利用这些系统调用,把他们都封装在了ListenAndServe中。
  Listen往下追究就是系统调用,所以我们重点看Serve:
  把分支代码收起来,只看主干,发现是一个for循环里面在不停地Accept,而这个Accept在没有连接时是阻塞的,当有连接时,起一个新的协程来处理。HttpServer如何处理请求的?一些前置工作
  处理请求的一行代码是,可以看出是每个连接单开了一个协程处理:goc。serve(connCtx)
  这里的connCtx代入了当前的Server对象:ctx:context。WithValue(baseCtx,ServerContextKey,srv)。。。connCtx:ctx
  而且还提供了修改它的hook方法srv。ConnContext,可以在每次Accept时修改原始的contextifcc:srv。ConnContext;cc!nil{connCtxcc(connCtx,rw)ifconnCtxnil{panic(ConnContextreturnednil)}}
  它的定义是:ConnContextoptionallyspecifiesafunctionthatmodifiesthecontextusedforanewconnectionc。TheprovidedctxisderivedfromthebasecontextandhasaServerContextKeyvalue。ConnContextfunc(ctxcontext。Context,cnet。Conn)context。Context
  但是如果按照我开头给的代码,你是没法修改srv。ConnContext的,可以改成这样来自定义:funcmain(){http。HandleFunc(hello,hello)server:http。Server{Addr::81,ConnContext:func(ctxcontext。Context,cnet。Conn)context。Context{returncontext。WithValue(ctx,hello,roshi)},}server。ListenAndServe()}
  同样的c。setState也提供了hook,可采取如上的方法设置,在每次连接状态改变时执行hook方法:c。setState(c。rwc,StateNew,runHooks)beforeServecanreturnConnStatespecifiesanoptionalcallbackfunctionthatiscalledwhenaclientconnectionchangesstate。SeetheConnStatetypeandassociatedconstantsfordetails。ConnStatefunc(net。Conn,ConnState)开始真正干活
  为了能看清楚Accept后,serve方法到底干了什么,我们再简化一下:func(cconn)serve(ctxcontext。Context){。。。for{w,err:c。readRequest(ctx)。。。serverHandler{c。server}。ServeHTTP(w,w。req)。。。}}
  serve也是一个大循环,循环里面主要是读取一个请求,然后将请求交给Handler处理。
  为什么是一个大循环呢?因为每个serve处理的是一个连接,一个连接可以有多次请求。
  读请求就显得比较枯燥乏味,按照Http协议,读出URL,header,body等信息。
  这里有个细节是在每次读取了一个请求后,还开了一个协程去读下一个请求,也算是做了优化吧。for{w,err:c。readRequest(ctx)。。。ifrequestBodyRemains(req。Body){registerOnHitEOF(req。Body,w。conn。r。startBackgroundRead)}else{w。conn。r。startBackgroundRead()}。。。}请求如何路由?
  当读取到一个请求后,便进入这一行代码:serverHandler{c。server}。ServeHTTP(w,w。req)
  ServeHTTP找到我们注册的Handler去处理,如果请求的URI是或请求Method是OPTIONS,则使用globalOptionsHandler,也就是说这类请求不需要我们手动处理,直接就返回了。
  对于我们注册的Handler也需要去寻找路由,这个路由的规则还是比较简单,主要由如下三条:如果注册了带host的路由,则按hostpath去寻找,如果没注册带host的路由,则按path寻找路由规则匹配以完全匹配优先,如果注册的路由规则最后一个字符是,则除了完全匹配外,还会以前缀查找
  举几个例子来理解一下:带host的匹配规则
  注册路由为http。HandleFunc(hello,hello)http。HandleFunc(127。0。0。1hello,hello2)
  此时如果执行curlhttp:127。0。0。1:81hello
  则会匹配到hello2,但如果执行curlhttp:localhost:81hello
  就匹配的是hello前缀匹配
  如果注册路由为http。HandleFunc(hello,hello)http。HandleFunc(127。0。0。1hello,hello2)
  注意第二个最后还有个,此时如果执行curlhttp:127。0。0。1:81helloroshi
  也能匹配到hello2,怎么样,是不是理解了?
  找到路由之后就直接调用我们开头注册的方法,如果我们往Response中写入数据,就能返回给客户端,这样一个请求就处理完成了。总结
  最后我们回忆下GoHttpServer的要点:用Go起一个HttpServer非常简单GoHttpServer本质是一个大循环,每当有一个新连接时,会起一个新的协程来处理每个连接的处理也是一个大循环,这个循环里做了读取请求、寻找路由、执行逻辑三件大事
  感谢能抽空看到这里,如果你能点赞、在看、分享,我会更加感激不尽
  搜索关注捉虫大师,后端技术分享,架构设计、性能优化、源码阅读、问题排查、踩坑实践

解构张爱玲为何她笔下的人物如此荒凉我不喜欢壮烈。我只是喜欢悲壮,更喜欢苍凉。壮烈只有力,没有美,似乎缺乏人性。张爱玲将人性解读剖析得淋漓尽致,这与她的人生经历是分不开的。张爱玲出生在一个没落的贵族世家,她的父亲张志货币的支付与储存本文是学习哥伦比亚大学佩里梅林货币银行学课程的思考。由于课程主要以货币的支付手段功能为出发点来探讨货币,虽然也有涉及货币的财富储藏功能,但显然财富储藏并没有得到支付手段的同等重视。女人这2种碱性食物要常吃,口臭没了,头发黑了,别不懂吃导语女人这2种碱性食物要常吃,口臭没了,头发黑了,不懂吃可惜了!大家好,我是傻姐美食,爱美之心,人皆有之。特别是女人,非常注重自己的外表,但是我们只要有一个健康的身体,才能有完美的大豆价格高开低走建议农户适时销售来源农民日报9月中旬,黑龙江大豆早熟品种收获上市,较去年提前约一周,贸易商毛粮(未过筛大豆)开秤收购价每斤2。953。15元,较去年开秤价每斤高0。20。25元,之后随着上市量增加总是用泥膜去黑头会不会导致毛孔变大?经常用泥膜并不会导致毛孔变大,但泥膜也去不了黑头。看一下泥膜的质地很多人误以为这就是火山泥或者河里挖的淤泥,当然不是,这也是配方产品,毕竟天然的泥浆很多微生物和细菌,不能直接上脸。瓷蕊毛孔粗大的原因是什么?什么导致毛孔粗大?每个人的皮肤上都覆盖着细小的毛发,除了手掌和脚掌。每个毛孔里都有毛囊。每个毛囊里都有一个皮脂腺,皮脂腺能产生油脂。当皮脂腺释放出一种叫做皮脂的油性物质时,它会生升每一个毛孔都是张爱玲每一次呼吸都与之相关丨记者手记相关报道详见黄心村张爱玲来到香港之后今天不是要讲爱情故事,普通的男欢女爱似乎也没有太多传颂的价值。思念成灾又如何,为你摘星写诗又怎样,都很难撇清自我感动和自我表现。清幽的人提出了更妆容显毛孔怪粉底,那是你缺了填毛孔这一步夏季冬季是俄国很反差的季节,就像油皮和干皮。夏季出油毛孔凸显,冬季太干又凸显毛孔,所以很多人会有脸颊毛孔过大的问题,上完彩妆。比如粉底隔离霜,总是觉得脸颊毛孔粗大的区域不是特别服帖女星离开P图赵丽颖宋轶李沁插秧毛孔,高圆圆杨幂瞬间显老平时我们看到的女明星相关资讯,她们都是妆容精致,皮肤白皙细腻赛过羊脂白玉,脸部紧致小巧宛如二八少女,让我们普通人经常羡慕明星每天208w保养皮肤,直接就冻龄在脸上了。但你可能不知道内调外敷敏感肌一次性解决毛孔粗大问题1。刷酸刷酸的目的是为了更好的清洁毛孔祛痘和闭口粉刺改善毛孔粗大和皮肤粗糙的问题,由于我是超级敏感肌,刷酸这个事确实需要非常谨慎,美国产的STRIDEX水杨酸棉片算是比较温和的刷酸乳液推荐这些乳液,长期坚持使用可起到收缩毛孔和美白的效果乳液推荐这些乳液,长期坚持使用可起到收缩毛孔和美白的效果!春雨蜂蜜乳液春雨护肤品牌很温和无刺激,很适合任何肤质的人群使用了。这一款蜂蜜原液含有87的蜂蜜原液,涂抹于脸部皮肤的时候不
车子档次越开越低的,都是些什么人?车子档次越开越低的人,其实也是明白人,很多人一开始买车都想买高端的,好一点的,也是考虑到方方面面,可是当一辆车开了几年以后,你会感觉车子这玩意其实就是一个代步工具,好车维修,保养费雪里红为什么要腌制?怎么腌制好吃?雪里蕻是秋储冬菜中的明星菜品,几乎每年一到这个时候,家里都会腌制个二三十斤!腌好的雪里蕻用来拌制虾皮小葱,或者炖豆腐包包子,都是不错的美味。那么雪里蕻为什么要腌制雪里蕻有一股辛辣特蒸馒头的面里要不要放盐白糖或者油?为什么?我们家虽然吃米饭比较多,但是我妈妈是一个很喜欢做面食的人,在我还很小时候就是如此了。那时候的印象里,我妈每次蒸出来又白又暄软的馒头都会高兴好半天,会一个个劲儿的跟我说你看今天这锅馒一个没有正式工作的女性,却有三百多个微信好友,这种情况正常吗?自从堂哥出去打工以后,堂嫂已经连续多年没有工作了,在家也不照顾孩子,还经常和不同的男人来往,婶子让堂哥离婚,直到去年,我发现了堂嫂的一个秘密后,我对婶子说,如果堂哥真的和堂嫂离婚了相信自己零点乐队激情山丹文图祁连月3月25日晚,五彩欢乐城群星演唱会,在张掖市山丹县火热进行。国内首屈一指的老牌流行摇滚乐队零点乐队,在五彩欢乐城激情演唱。动感十足震撼人心的摇滚乐响起,主唱老五登场。一声火种燃烧元气满满长沙音乐节市场复苏众多歌手来长捧场火种燃烧元气满满长沙音乐节市场复苏,丰富了年轻人周末文化生活,吸引了众多歌手来长捧场曾经的超女江映蓉献唱火种音乐节。均为资料图片李莎旻子这么大的台子,是朋友圈里都在传的音乐节吗?不网曝刘亦菲在梦华录中不止一个替身,爆料者杖责那一场也有替身在2023微博之夜的盛典上,80后女星们一个比一个闪亮,简直让观众们看花了眼。特别是刘亦菲,她凭借孔雀公主造型和微博Queen称号成功获得更多人的喝彩,又妥妥地火了一把。在为刘亦菲微博之夜杀疯了!CP大乱炖是救命稻草,还是内娱新流量密码?一年一度的微博之夜堪称国内明星的团建,各路流量大咖齐聚一堂。所有粉丝加班加点疯狂打call,只为迎接这场内娱狂欢盛宴。各种意想不到的笑点以及抓马事件都会让这一夜变得精彩纷呈。而这次樊振东20分钟横扫马龙夺得热身赛冠军,马龙放水了吗?球迷们万众期待的龙胖大战,结果非常出人意料地以马龙溃败而结束了。整个比赛过程小胖也仅仅用了20分钟。马龙在热身赛一路走来,状态是越来越好,为何到了决赛却被小胖无情横扫呢?有球迷说,专为赛道而生,劳力士的这些迪通拿们我们应该怎么选?导读向来只做基础款工具腕表的劳力士,在天行者出现之前迪通拿是劳力士最复杂的腕表,也正是因为三眼计时的颜值让这个型号成为当代表友追捧的角色,迪通拿因佛罗里达州迪通拿国际赛道而得名,它请问腕表什么带子比较舒服?舒适钛,轻便亲肤一般的机械表可以分成三大类正装表运动表休闲表。而上手比较舒服的就都可以称之为休闲表,休闲表可以是正装表,也可以是运动表,它的界定范围并不严格。不过休闲表还有一个很大
友情链接:快好找快生活快百科快传网中准网文好找聚热点快软网