Согласно документации gRPC, клиенты могут указать крайние сроки, чтобы определить, как долго клиент будет ждать на сервере перед завершением с ошибкой DEADLINE_EXCEEDED
. В документации упоминается, что разные языки имеют разные реализации и что некоторые языки не имеют значений по умолчанию.
Действительно, быстрое сочетание клавиш CTRL + F для "крайнего срока" в документации Go gRPC не дает результатов. . Что я обнаружил, так это WithTimeout
на дозвоне для TCP-соединения.
Реализовано следующим образом (из примера helloworld):
package main
import (
"log"
"os"
"time"
"golang.org/x/net/context"
"google.golang.org/grpc"
pb "google.golang.org/grpc/examples/helloworld/helloworld"
)
const (
address = "localhost:50051"
defaultName = "world"
deadline = 20
)
func main() {
// Set up a connection to the server with a timeout
conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithTimeout(time.Duration(deadline)*time.Second)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)
}
Код вызовет ошибку, только если клиент не может подключиться через 20 секунд. Результат будет примерно таким:
2016/05/24 09:02:54 grpc: Conn.resetTransport failed to create client transport: connection error: desc = "transport: dial tcp [::1]:3265: getsockopt: connection refused"; Reconnecting to "localhost:3265"
2016/05/24 09:02:54 Failed to dial localhost:3265: grpc: timed out trying to connect; please retry.
2016/05/24 09:02:54 could not greet: rpc error: code = 2 desc = grpc: the client connection is closing
Как указано в заголовке вопроса, система, с которой я работаю, является одноранговой, поэтому нет центрального, всегда работающего сервера, и поэтому система повторных попыток, которую реализует gRPC, прекрасна. Однако я на самом деле ищу крайние сроки, потому что, если удаленный компьютер подключается, но серверу требуется> 20 секунд, чтобы ответить, в контексте WithTimeout
не возникнет никаких исключений.
Для меня полной победой будет система тайм-аутов / дедлайнов, где:
- если клиент не может подключиться, по истечении тайм-аута возвращается ошибка
- если клиент подключается, но сервер не отвечает до истечения времени ожидания, возвращается ошибка.
- если клиент подключается, но соединение прерывается до истечения времени ожидания, возвращается ошибка.
Однако я чувствую, что мне понадобится некоторая комбинация управления подключением плюс управление сроками gRPC. Кто-нибудь знает, как в Go реализовать дедлайны?