Go标准包-http包server

http serve

只需要几行代码就可以启动http服务

func main()  {
    http.HandleFunc("/", sayHelloWorld) //路由处理, sayHelloWorld是函数变量, handler func(ResponseWriter, *Request)
    err := http.ListenAndServe(":9091", nil) //监听9091端口
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

1.路由处理-ServeMux

type ServeMux struct {
    mu    sync.RWMutex
    m     map[string]muxEntry
    es    []muxEntry // slice of entries sorted from longest to shortest.
    hosts bool       // whether any patterns contain hostnames
}
http包会有个全局ServeMux,也就是DefaultServeMux,所以一般不用我们实例它
1.1注册路由
type HandlerFunc func(ResponseWriter, *Request) //定义了函数类,这个类的变量都实现了接口http.Handler

// HandleFunc registers the handler function for the given pattern.
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
    mux.Handle(pattern, HandlerFunc(handler))
}

func (mux *ServeMux) Handle(pattern string, handler Handler) {    
    e := muxEntry{h: handler, pattern: pattern}
    mux.m[pattern] = e    //实际注册到ServeMux.m属性中
}

2.服务对象-Serve

type Server struct {    
    Addr string
    Handler Handler // handler to invoke, http.DefaultServeMux if nil

    TLSConfig *tls.Config
    ReadTimeout time.Duration    
    ReadHeaderTimeout time.Duration    
    WriteTimeout time.Duration
    IdleTimeout time.Duration    
    MaxHeaderBytes int
    TLSNextProto map[string]func(*Server, *tls.Conn, Handler)

    ConnState func(net.Conn, ConnState)    
    ErrorLog *log.Logger
    BaseContext func(net.Listener) context.Context    
    ConnContext func(ctx context.Context, c net.Conn) context.Context
    inShutdown atomicBool // true when when server is in shutdown

    disableKeepAlives int32     // accessed atomically.
    nextProtoOnce     sync.Once // guards setupHTTP2_* init
    nextProtoErr      error     // result of http2.ConfigureServer if used

    mu         sync.Mutex
    listeners  map[*net.Listener]struct{}
    activeConn map[*conn]struct{}
    doneChan   chan struct{}
    onShutdown []func()
}
2.1.监听端口
func ListenAndServe(addr string, handler Handler) error {
    server := &Server{Addr: addr, Handler: handler} //handler一开始是nil
    return server.ListenAndServe()
}

func (srv *Server) ListenAndServe() error {    
    addr := srv.Addr    
    ln, err := net.Listen("tcp", addr) //通过net监听端口,net.listener
    return srv.Serve(ln)
}

func (srv *Server) Serve(l net.Listener) error {
    for {
        rw, err := l.Accept() //监听到客户端有连接,返回net.conn        
        c := srv.newConn(rw) //把net.conn封装为http.conn
        go c.serve(connCtx) 
    }
}
2.2 连接对象-http.conn
type conn struct {

    server *Server
    cancelCtx context.CancelFunc
    rwc net.Conn
    remoteAddr string
    tlsState *tls.ConnectionState
    werr error

    // r is bufr's read source. It's a wrapper around rwc that provides
    // io.LimitedReader-style limiting (while reading request headers)
    // and functionality to support CloseNotifier. See *connReader docs.
    r *connReader

    // bufr reads from r.
    bufr *bufio.Reader

    // bufw writes to checkConnErrorWriter{c}, which populates werr on error.
    bufw *bufio.Writer

    // lastMethod is the method of the most recent request
    // on this connection, if any.
    lastMethod string

    curReq atomic.Value // of *response (which has a Request in it)

    curState struct{ atomic uint64 } // packed (unixtime<<8|uint8(ConnState))

    // mu guards hijackedv
    mu sync.Mutex

    // hijackedv is whether this connection has been hijacked
    // by a Handler with the Hijacker interface.
    // It is guarded by mu.
    hijackedv bool
}
处理连接
func (c *conn) serve(ctx context.Context) {
    c.remoteAddr = c.rwc.RemoteAddr().String()
    c.r = &connReader{conn: c}
    c.bufr = newBufioReader(c.r)
    c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)

    for {
        w, err := c.readRequest(ctx) //获取request对象,response对象
        c.curReq.Store(w)

        serverHandler{c.server}.ServeHTTP(w, w.req) //把requset,response交个路由器处理
        w.cancelCtx()        
        c.rwc.SetReadDeadline(time.Time{})
    }
}

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
    handler := sh.srv.Handler //一开始listenAndServe时,Handler是nil.
    if handler == nil {
        handler = DefaultServeMux
    }    
    handler.ServeHTTP(rw, req) //最终交给DefaultServeMux处理
}
2.3.路由分发
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
    h, _ := mux.Handler(r) //查询路由获取对应的HandlerFunc
    h.ServeHTTP(w, r)
}

3.1根据path获取handler

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

返回http.Handler,注册的函数都实现了http.Handler接口。

func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {
    host := stripHostPort(r.Host)
    path := cleanPath(r.URL.Path)
    return mux.handler(host, r.URL.Path)
}
func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {    
    h, pattern = mux.match(path)
    return
}
func (mux *ServeMux) match(path string) (h Handler, pattern string) {
    // Check for exact match first.
    v, ok := mux.m[path]
    if ok {
        return v.h, v.pattern
    }
    return nil, ""
}

总结

1.ServeMux 等于srv.Handler,保存了路由map,实现了ServeHTTP()方法(conn会把w,r传到这个方法去),很多自定义http服务,都是重写srv.Handler
2.Serve 监听端口,管理连接
3.接口Handler 注册路由的函数必须实现这个接口,为了方便专门定义了一个类型HandlerFunc,只要是HandlerFunc类型的变量,就是实现了接口Handler

type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

4.serverHandler 独立的结构,为了串联conn与srv.Handler
在conn连接对象中,接受的请求通过serverHandler{c.server}.ServeHTTP(w, w.req),最终handler.ServeHTTP()

区块链节点使用http包实现json-rpc功能

构造httpServer对象,作为srv.Handler. 连接对象会把w,r传给httpServer的ServeHTTP方法

func (h *httpServer) start() error {
    h.server = &http.Server{Handler: h} //创建标准库srv, srv.Handler为httpServer
    listener, err := net.Listen("tcp", h.endpoint)
    h.listener = listener
    go h.server.Serve(listener)
    return nil
}
-------------------------------------------------
func (h *httpServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    rpc := h.httpHandler.Load().(*rpcHandler) //这个是rpc.NewServer()创建的
    rpc.ServeHTTP(w, r)//又转给rpcHandler
    return
}

这里其实是多封装了一层,最终处理的Handler对象是rpc.NewServer(),所有这个rpcHandler等于标准库的srv.Handler,需要保存路由map,同时实现ServeHTTP方法。

本作品采用《CC 协议》,转载必须注明作者和本文链接
用过哪些工具?为啥用这个工具(速度快,支持高并发...)?底层如何实现的?
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!