• Go http2 和 h2c


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

    http/1.1 的服务器

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

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

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

    http/1.1 的服务器 with TLS

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

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

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

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

    1、 创建CA证书

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

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

    2、 创建证书

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

    免费证书

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

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

    package main
    
    import (
        "crypto/tls"
        "log"
        "net/http"
    
        "golang.org/x/crypto/acme/autocert"
    )
    
    func main() {
        certManager := autocert.Manager{
            Prompt:     autocert.AcceptTOS,
            HostPolicy: autocert.HostWhitelist("example.com"), 
            Cache:      autocert.DirCache("certs"),
        }
    
        http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
            w.Write([]byte("Hello world"))
        })
    
        server := &http.Server{
            Addr: ":443",
            TLSConfig: &tls.Config{
                GetCertificate: certManager.GetCertificate,
            },
        }
    
        go http.ListenAndServe(":80", certManager.HTTPHandler(nil))
    
        log.Fatal(server.ListenAndServeTLS("", "")) //Key and cert are coming from Let's Encrypt
    }

    或者更简单的:

    log.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 )

    HTTP/2

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

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

    package main
    
    import (
    	"log"
    	"net/http"
    	"time"
    
    	"golang.org/x/net/http2"
    )
    
    const idleTimeout = 5 * time.Minute
    const activeTimeout = 10 * time.Minute
    
    func main() {
    	var srv http.Server
    	//http2.VerboseLogs = true
    	srv.Addr = ":8972"
    
    	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    		w.Write([]byte("hello http2"))
    	})
    
    	http2.ConfigureServer(&srv, &http2.Server{})
    
    	go func() {
    		log.Fatal(srv.ListenAndServeTLS("server.crt", "server.key"))
    	}()
    	select {}
    }

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

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

    h2c

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

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/http"
    
    	"golang.org/x/net/http2"
    	"golang.org/x/net/http2/h2c"
    )
    
    func main() {
    	mux := http.NewServeMux()
    	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    		fmt.Fprint(w, "Hello h2c")
    	})
    	s := &http.Server{
            Addr:    ":8972",
            Handler: mux,
        }
        http2.ConfigureServer(s, &http2.Server{})
        log.Fatal(s.ListenAndServe())
    }

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

    客户端代码如下:

    package main
    
    import (
        "crypto/tls"
        "fmt"
        "log"
        "net"
        "net/http"
    
        "golang.org/x/net/http2"
    )
    
    func main() {
        client := http.Client{
            // Skip TLS dial
            Transport: &http2.Transport{
                AllowHTTP: true,
                DialTLS: func(network, addr string, cfg *tls.Config) (net.Conn, error) {
                    return net.Dial(network, addr)
                },
            },
        }
    
        resp, err := client.Get("http://localhost:8972")
        if err != nil {
            log.Fatal(fmt.Errorf("error making request: %v", err))
        }
        fmt.Println(resp.StatusCode)
        fmt.Println(resp.Proto)
    }

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

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

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

  • 相关阅读:
    Install Java on Ubuntu server
    Java 空引用访问静态不会发生空指针异常
    Java 什么时候使用static
    Java 空指针异常
    java 方法的返回值
    python中直接复制,浅拷贝,深拷贝
    python 操作ppt转换为pdf
    数组排序
    qooxdoo框架环境搭建
    python 链表实现 双向链表和单向循环链表
  • 原文地址:https://www.cnblogs.com/gao88/p/9840609.html
Copyright © 2020-2023  润新知