Go http2 和 h2c

Posted Golang语言社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go http2 和 h2c相关的知识,希望对你有一定的参考价值。

了解一下http2和h2c (HTTP/2 over TCP,HTTP/2 without TLS)。

1、http/1.1 的服务器

我们经常会在代码中启动一个http服务器,最简单的http/1.1服务器如下所示:

1http.Handle("/foo", fooHandler)
2http.HandleFunc("/bar"func(w http.ResponseWriter, r *http.Request) {
3    fmt.Fprintf(w, "Hello, %q"html.EscapeString(r.URL.Path))
4})
5log.Fatal(http.ListenAndServe(":8080"nil))


使用Go开发web服务非常的简单,快速。

2、http/1.1 的服务器 with TLS

如果想让http/1.1服务器支持TLS, 可以使用如下的代码:

1http.Handle("/foo", fooHandler)
2http.HandleFunc("/bar"func(w http.ResponseWriter, r *http.Request) {
3    fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
4})
5log.Fatal(http.http.ListenAndServeTLS(":443""server.crt""server.key",nil))


至于server.crt 和 server.key,你可以使用你从CA购买的证书,你也可以使用下面的测试证书。

为了测试,你可以创建CA证书和你的服务器使用的证书。

1、 创建CA证书

1$ openssl genrsa -out rootCA.key 2048
2$ openssl req -x509 -new -nodes -key rootCA.key -days 1024 -out rootCA.pem


然后把rootCA.pem加到你的浏览器的证书中

2、 创建证书

1$ openssl genrsa -out server.key 2048
2$ openssl req -new -key server.key -out server.csr
3$ openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 500


3、免费证书

如果你不想从CA花钱购买证书, 也不想配置测试证书,那么你可以使用let's encrypt的免费证书, 而且let's encrypt目前支持通配符证书,使用也是很方便的。

Go的扩展包中提供了let's encrypt的支持。

 1package main
2import (
3    "crypto/tls"
4    "log"
5    "net/http"
6    "golang.org/x/crypto/acme/autocert"
7)
8func main() {
9    certManager := autocert.Manager{
10        Prompt:     autocert.AcceptTOS,
11        HostPolicy: autocert.HostWhitelist("example.com"), 
12        Cache:      autocert.DirCache("certs"),
13    }
14    http.HandleFunc("/"func(w http.ResponseWriter, r *http.Request) {
15        w.Write([]byte("Hello world"))
16    })
17    server := &http.Server{
18        Addr: ":443",
19        TLSConfig: &tls.Config{
20            GetCertificate: certManager.GetCertificate,
21        },
22    }
23    go http.ListenAndServe(":80", certManager.HTTPHandler(nil))
24    log.Fatal(server.ListenAndServeTLS("""")) //Key and cert are coming from Let's Encrypt
25}


或者更简单的:


1log.Fatal(http.Serve(autocert.NewListener("example.com"), handler))


看上面的例子, 把example.com换成你的域名,证书暂存在certs文件夹。autocert会定期自动刷新,避免证书过期。它会自动申请证书,并进行验证。

不过比较遗憾的是, autocert目前不支持通配符域名。

HostWhitelist returns a policy where only the specified host names are allowed. Only exact matches are currently supported. Subdomains, regexp or wildcard will not match.

通配符(ACME v2)的支持也已经完成了,但是迟迟未通过review,所以你暂时还不能使用这个特性。 (issue#21081)

4、HTTP/2

Go 在 1.6的时候已经支持 HTTP/2 了, 1.8 开始支持PUSH功能,你什么时候开始采用HTTP/2的呢?

Go的http/2使用也非常简单,但是必须和TLS一起使用。

 1package main
2import (
3    "log"
4    "net/http"
5    "time"
6    "golang.org/x/net/http2"
7)
8const idleTimeout = 5 * time.Minute
9const activeTimeout = 10 * time.Minute
10func main() {
11    var srv http.Server
12    //http2.VerboseLogs = true
13    srv.Addr = ":8972"
14    http.HandleFunc("/"func(w http.ResponseWriter, r *http.Request) {
15        w.Write([]byte("hello http2"))
16    })
17    http2.ConfigureServer(&srv, &http2.Server{})
18    go func() {
19        log.Fatal(srv.ListenAndServeTLS("server.crt""server.key"))
20    }()
21    select {}
22}


http2封装并隐藏了http/2的处理逻辑,对于用户来说,可以不必关心内部的具体实现,想http/1.1一样简单的使用即可。

这里的证书可以使用上面提到证书,或者你购买的1证书,或者免费let's encrypt证书。

5、h2c

上面我们说Go的http/2必须使用TLS是不严谨的,如果你想不使用TLS,你可以使用最近添加的h2c功能。

 1package main
2import (
3    "fmt"
4    "log"
5    "net/http"
6    "golang.org/x/net/http2"
7    "golang.org/x/net/http2/h2c"
8)
9func main() {
10    mux := http.NewServeMux()
11    mux.HandleFunc("/"func(w http.ResponseWriter, r *http.Request) {
12        fmt.Fprint(w, "Hello h2c")
13    })
14    s := &http.Server{
15        Addr:    ":8972",
16        Handler: mux,
17    }
18    http2.ConfigureServer(s, &http2.Server{})
19    log.Fatal(s.ListenAndServe())
20}


使用起来也很简单,单数目前浏览器对http/2都是采用TLS的方式,所以用浏览器访问这个服务的话会退化为http/1.1的协议,测试的话你可以使用Go实现客户端的h2c访问。

客户端代码如下:

 1package main
2import (
3    "crypto/tls"
4    "fmt"
5    "log"
6    "net"
7    "net/http"
8    "golang.org/x/net/http2"
9)
10func main() {
11    client := http.Client{
12        // Skip TLS dial
13        Transport: &http2.Transport{
14            AllowHTTP: true,
15            DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
16                return net.Dial(network, addr)
17            },
18        },
19    }
20    resp, err := client.Get("http://localhost:8972")
21    if err != nil {
22        log.Fatal(fmt.Errorf("error making request: %v", err))
23    }
24    fmt.Println(resp.StatusCode)
25    fmt.Println(resp.Proto)
26}


这个功能的讨论2016年就开始了(issue#14141),最终5月份的这个功能加上了,这样你就可以在没有TLS使用http/2高性能的特性了。

虽然有一些第三方的实现,但是显然使用官方库是更好的选择。


干货来了!!!为了让更多的小伙伴喜欢Golang、加入Golang之中来,Golang语言社区发起人彬哥联合业界大牛共同推出了Go语言基础、进阶、提高课程,目前已在网易云课堂限时特价分享,希望有兴趣的朋友们多多分享和支持!

长按扫描下方二维码或点击阅读原文,即可了解课程详情!

Go http2 和 h2c


版权申明:内容来源网络,版权归原创者所有。除非无法确认,我们都会标明作者及出处,如有侵权烦请告知,我们会立即删除并表示歉意。谢谢。



Golang语言社区

ID:Golangweb

www.bytedancing.com

游戏服务器架构丨分布式技术丨大数据丨游戏算法学习


以上是关于Go http2 和 h2c的主要内容,如果未能解决你的问题,请参考以下文章

Apache HTTP2 h2c 模式无法正常工作

springboot搭建http2服务器和h2c服务器 h2 的http/https 请求服务器

Netty HTTP2 帧转发/代理 - 管道配置问题

h2csmuggler:一款隐蔽性极强的HTTP2明文通信工具

Nginx 是不是支持以明文形式从 http/1.1 升级 http/2 (h2c)

深入理解 WEB协议HTTP2