context裡的超時時間是怎麼在微服務之間傳遞的

cs_wu發表於2024-03-17

題目:有A、B三個服務,呼叫鏈路為:A->B,為了控制呼叫的超時時間。A服務生成一個context,超時時間設定為3s,在A服務呼叫B服務的時候會把context傳給B服務。這樣子就能控制呼叫超時時間為3s,請問context裡的超時是怎麼在兩個服務之間傳遞的,透過什麼傳遞的?

在Go語言中,當微服務A需要將context的資訊傳遞給微服務B時,實際上並不是直接將context物件透過網路傳送。相反,context中的某些資訊(如截止時間、取消訊號等)會被提取出來,並作為請求的一部分傳送給微服務B。

以下是context資訊如何在網路上從微服務A傳遞到微服務B的步驟:

1.提取資訊:在微服務A中,當準備發起對微服務B的請求時,會從當前的context中提取出需要傳遞的資訊。這通常包括截止時間(如果有的話)和取消訊號。

2.設定請求後設資料:這些資訊會被設定到請求的後設資料(Metadata)中。對於HTTP請求,這可能意味著將截止時間轉換為超時頭(如果協議支援),或者將取消訊號轉換為某種形式的請求標識,以便在必要時能夠中斷處理。對於gRPC,可以使用後設資料或特定的RPC上下文來傳遞這些資訊。

3.傳送請求:微服務A發起一個gRPC請求時,它會將後設資料附加到請求頭(Headers)中,這些後設資料包含了關於請求的各種資訊,如認證 資訊、使用者代理等。後設資料在請求頭中時鍵值對的形式傳遞。

4.解析後設資料:微服務B接收到請求後,會從請求頭中解析請求的後設資料,從中提取出截止時間和取消訊號(如果有的話)。然後,微服務B會建立一個新的context物件,並將這些資訊設定到新的context中。

5.處理請求:微服務B使用新建立的context來處理請求。這意味著如果微服務A的context被取消,微服務B可以透過檢查其自己的context來得知這一點,並相應地中斷處理。

需要注意的是,這種傳遞方式並不是自動的;開發者需要顯式地從context中提取資訊,並將其設定到請求中。此外,不同的通訊協議和框架可能有不同的方式來處理context資訊的傳遞。例如,gRPC提供了專門的上下文傳播機制,而HTTP則可能需要開發者自行實現一些邏輯來傳遞這些資訊。

最後,還要考慮到安全性和隱私性問題。不應該將敏感資訊或不應暴露給微服務B的資訊透過context傳遞。因此,在設計和實現這種傳遞機制時,需要仔細考慮哪些資訊應該被傳遞,以及如何安全地傳遞這些資訊。

grpc超時傳遞是透過metadata進行傳遞的,最終會被轉化為grpc-timeout的值,程式碼如下:

if v := r.Header.Get("grpc-timeout"); v != "" {
  to, err := decodeTimeout(v)
  if err != nil {
   return nil, status.Errorf(codes.Internal, "malformed time-out: %v", err)
  }
  st.timeoutSet = true
  st.timeout = to
}

 從請求頭裡取出超時時間的後設資料,然後再透過得到的值構建一個context。 

相關文章