GO 如何实现 页面非阻塞?

2018-06-20 16:27:27 +08:00
 lauix
如题

页面非阻塞,就是一个页面访问要 5 秒,10 人访问不排队,并发进行。

Nodejs 自带,Python tornado gevent 都可以实现。

今天研究 golang 发现找不到如何实现。。。

研究了 channel 还是不行

问问 v2 的大神们,有解决方法吗? or 是否有 go web 的高性能解决方案。

基于 web 框架 iris 开发研究测试。
7633 次点击
所在节点    程序员
66 条回复
wei193
2018-06-20 19:05:47 +08:00
13 楼上不是说了吗? time.Sleep 的锅
yanhejihe
2018-06-20 19:07:12 +08:00
哇,在我测试 demo 过程就破案了,应该就是浏览器的问题。
wei193
2018-06-20 19:11:50 +08:00
switch r.URL.Path {
case "/":

log.Println(1)
s.Lock()
// time.Sleep
log.Println(2)
fmt.Fprintf(w, "hello word: %d\n", time.Now().Unix())

default:
log.Println(1)
s.Unlock()
// time.Sleep
log.Println(2)
fmt.Fprintf(w, "hello word: %d\n", time.Now().Unix())
}

以上代码可以实现并发 所以我觉得是 time.Sleep 问题,测试环境 go version go1.9 darwin/amd64
wei193
2018-06-20 19:16:02 +08:00
@wei193 回复 43 楼 测试有误, 应该是 goroutine 针对连接的 因为将上面的代码修改 time.Sleep 一样是并发
elvodn
2018-06-20 19:19:42 +08:00
``` go
package main

import (
"fmt"
"net/http"
"time"
)

func handler(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "text/plain")

fmt.Printf("[%v] start %v %v \n", time.Now(), req.RemoteAddr, req.URL)
time.Sleep(10 * time.Second)
fmt.Printf("[%v] end %v %v\n", time.Now(), req.RemoteAddr, req.URL)
}

func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8088", nil)
}

```
1.10.3 没问题啊, 浏览器内多个请求是阻塞的
icexin
2018-06-20 19:41:43 +08:00
chrome 的锅。打开 console,看下请求时间主要在 stalled 上,由于两次请求是同一个资源,chrome 加了一把锁,导致同步请求。如果把 console 里面的 disable cache 勾上就没事了。
见这篇文章 http://fex.baidu.com/blog/2015/01/chrome-stalled-problem-resolving-process/
Shakeitin
2018-06-20 19:44:59 +08:00

在 34 楼之后居然能再续十楼,惊了
ps: 两边时钟不准,勿细究
pathbox
2018-06-20 20:01:03 +08:00
@icexin 可以理解为同一个 Chrome 访问同一个资源加锁吗?不同的 Chrome 是不会加锁的吧?
icexin
2018-06-20 20:15:52 +08:00
看着是这样的,我一个开隐身,一个不开就没问题
iceheart
2018-06-20 20:30:23 +08:00
pipeline
scnace
2018-06-20 20:48:46 +08:00
你们真的不是写 go test 测试 但是去用浏览器试这个问题的吗 hhh
rrfeng
2018-06-20 20:57:07 +08:00
果然是浏览器的问题,跟我预想的差不多。

Chrome 总有些奇怪的骚操作
Reficul
2018-06-20 21:07:54 +08:00
Go 的 http 服务器本来就是一个请求一个 goroute 的。想写出阻塞的反而有点难度。
fan123199
2018-06-20 21:44:41 +08:00
@Reficul 我关注这个问题,就是我前端时间需要用阻塞来处理一个问题。 后来用了 mutex lock 来解决。想不到是个 chrome 还有这种问题。还有一个现象,如果你在 chrome 打开这个网页,然后点 F5 刷新,就不会阻塞。
karllynn
2018-06-20 21:46:10 +08:00
楼主这个问题看得我一愣一愣的
ToT
2018-06-20 21:55:00 +08:00
@ZSeptember 非常有用的链接,居然是第一次知道这个大牛。
RubyJack
2018-06-20 22:20:40 +08:00
1. time.Sleep 当然不是主线程阻塞
2. 比起锁,感觉像是 http 持久连接带来的问题
heimeil
2018-06-20 22:43:54 +08:00
同时请求两个一样的 URL,Chrome 会等待第一个请求返回头部信息里的缓存控制规则,第二次请求会再带上缓存规则(如果有的话)在请求头里面,这是 Chrome 的缓存控制优化机制,节省服务器资源,而两个不同的 URL 同时请求就没这种问题,比如 /foo 和 /bar。

可以了解一下 HTTP 缓存:
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching?hl=zh-cn
lazyago
2018-06-20 23:24:31 +08:00
如果是浏览器问题,那为什么题主使用 tornado 却没有复现此问题?
liuxey
2018-06-21 09:14:11 +08:00
厉害了,我第一次发现浏览器会串化相同请求。 👍

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/464449

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX