go-micro服务调用过程(草稿,未整理)

asm_amd64.s

TEXT runtime·goexit(SB),NOSPLIT,$0-0
	BYTE	$0x90	// NOP
	CALL	runtime·goexit1(SB)	// does not return
	// traceback from goexit1 must hit code range of goexit
	BYTE	$0x90	// NOP

runtime-> asm_amd64.s->net/http/server.go:1739

	// Serve a new connection.
	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)
		if c.r.remain != c.server.initialReadLimitSize() {
			// If we read any bytes off the wire, we're active.
			c.setState(c.rwc, StateActive)
		}
	
		.....
	
		serverHandler{c.server}.ServeHTTP(w, w.req)//先构造一个server,调用开始
		w.cancelCtx()
		if c.hijacked() {
			return
		}
		....

2.调用ServeHTTP

	func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
		handler := sh.srv.Handler//获取server
		if handler == nil {
			handler = DefaultServeMux
		}
		if req.RequestURI == "*" && req.Method == "OPTIONS" {//判断是否为跨域访问
			handler = globalOptionsHandler{}
		}
		handler.ServeHTTP(rw, req)
	}

reflect/value.go

func (v Value) call(op string, in []Value) []Value {
	// Get function pointer, type.
	......
	call(frametype, fn, args, uint32(frametype.size), uint32(retOffset))

	// For testing; see TestCallMethodJump.
	if callGC {
		runtime.GC()
	}
	......

asm_amd64.s

	TEXT reflect·call(SB), NOSPLIT, $0-0
	JMP	·reflectcall(SB)

micro/h2c/h2c.go

// ServeHTTP will serve with an HTTP/2 connection if possible using the `H2Server`.
// The request will be handled by the wrapped `Handler` in any case.

func (h *HandlerH2C) ServeHTTP(
					w http.ResponseWriter, 
					req *http.Request) {
	// HTTP/2 With Prior Knowledge
	if req.Method == "PRI" && req.URL.Path == "*" && req.ProtoMajor == 2 {
		// log.Debugf("Attempting h2c with prior knowledge.")
		conn, err := initH2CWithPriorKnowledge(w)
		if err != nil {
			// log.Debugf("Error h2c with prior knowledge: %v", err)
			return
		}
		defer conn.Close()
		h2cSrv := &http2.Server{}
		h2cSrv.ServeConn(conn, &http2.ServeConnOpts{Handler: h.Handler})
		return
	}

// HTTP/2 Upgrade
	if conn, err := h2cUpgrade(w, req); err == nil {
		defer conn.Close()
		h2cSrv := &http2.Server{}
		h2cSrv.ServeConn(conn, &http2.ServeConnOpts{Handler: h.Handler})
		return
	}

	// Everything else
	h.Handler.ServeHTTP(w, req)
}

micro/go-micro/server/rpc-server.go

// ServeConn serves a single connection
func (s *rpcServer) ServeConn(sock transport.Socket) {
	defer func() {
		// close socket
		sock.Close()
		...
		...
		// create a wrapped function
		handler := func(ctx context.Context, req Request, rsp interface{}) error {
			return r.**ServeRequest**(ctx, req, rsp.(Response))
		}

		for i := len(s.opts.HdlrWrappers); i > 0; i-- {
			handler = s.opts.HdlrWrappers[i-1](handler)
		}

		// TODO: handle error better
		if err := handler(ctx, request, response); err != nil {
			// write an error response
			err = rcodec.Write(&codec.Message{
				Header: msg.Header,
				Error:  err.Error(),
				Type:   codec.Error,
			}, nil)
			// could not write the error response
			if err != nil {
				log.Logf("rpc: unable to write error response: %v", err)
			}
			s.wg.Done()
			return
		}

		// done
		s.wg.Done()
	}
}

net/http/server.go

// ServeHTTP dispatches the request to the handler whose
// pattern most closely matches the request URL.
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
	if r.RequestURI == "*" {
		if r.ProtoAtLeast(1, 1) {
			w.Header().Set("Connection", "close")
		}
		w.WriteHeader(StatusBadRequest)
		return
	}
	h, _ := mux.Handler(r)
	h.ServeHTTP(w, r)
}
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}

micro/go-micro/transport/http-transport.go

func (h *httpTransportListener) Accept(fn func(Socket)) error {
	// create handler mux
	mux := http.NewServeMux()

	// register our transport handler
	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		var buf *bufio.ReadWriter
		var con net.Conn

		// read a regular request
		if r.ProtoMajor == 1 {
			b, err := ioutil.ReadAll(r.Body)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			r.Body = ioutil.NopCloser(bytes.NewReader(b))
			// hijack the conn
			hj, ok := w.(http.Hijacker)
			if !ok {
				// we're screwed
				http.Error(w, "cannot serve conn", http.StatusInternalServerError)
				return
			}

			conn, bufrw, err := hj.Hijack()
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			defer conn.Close()
			buf = bufrw
			con = conn
		}

		// save the request
		ch := make(chan *http.Request, 1)
		ch <- r

		fn(&httpTransportSocket{
			ht:     h.ht,
			w:      w,
			r:      r,
			rw:     buf,
			ch:     ch,
			conn:   con,
			local:  h.Addr(),
			remote: r.RemoteAddr,
		})
	})

	// get optional handlers
	if h.ht.opts.Context != nil {
		handlers, ok := h.ht.opts.Context.Value("http_handlers").(map[string]http.Handler)
		if ok {
			for pattern, handler := range handlers {
				mux.Handle(pattern, handler)
			}
		}
	}

	// default http2 server
	srv := &http.Server{
		Handler: mux,
	}

	// insecure connection use h2c
	if !(h.ht.opts.Secure || h.ht.opts.TLSConfig != nil) {
		srv.Handler = &h2c.HandlerH2C{
			Handler:  mux,
			H2Server: &http2.Server{},
		}
	}

	// begin serving
	return srv.Serve(h.listener)
}

micro/go-micro/server/rpc-router.go

func (router *router) ServeRequest(ctx context.Context, r Request, rsp Response) error {
	sending := new(sync.Mutex)
	service, mtype, req, argv, replyv, keepReading, err := router.readRequest(r)
	log.Log("rpc_router==ServeRequest 打印 req=9=>>",req)
	if err != nil {
		if !keepReading {
			return err
		}
		// send a response if we actually managed to read a header.
		if req != nil {
			router.freeRequest(req)
		}
		return err
	}

	return service.call(ctx, router, sending, mtype, req, argv, replyv, rsp.Codec())
}

micro/go-micro/server/rpc-server.go

func (s *rpcServer) Start() error {
	registerDebugHandler(s)
	config := s.Options()

	// start listening on the transport
	ts, err := config.Transport.Listen(config.Address)
	if err != nil {
		return err
	}
	...
	...
	go func() {
		for {
			// listen for connections
			err := ts.Accept(s.ServeConn)

			// TODO: listen for messages
			// msg := broker.Exchange(service).Consume()

			select {
			// check if we're supposed to exit
			case <-exit:
				return
			// check the error and backoff
			default:
				if err != nil {
					log.Logf("Accept error: %v", err)
					time.Sleep(time.Second)
					continue
				}
			}

			// no error just exit
			return
		}
	}()
	...
	...
	return nil
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值