Отправка сообщений GRPC через определенный порт

Я запускаю сервер GRPC (сервер A), прослушивающий определенный порт. Я хочу иметь возможность отправлять сообщения на другой сервер (сервер B), и чтобы сервер B записывал входящий адрес соединения с сервером A, чтобы он мог позже связаться с сервером A.

На сервере A я прослушиваю порт и создаю такой контекст:

lis, err := net.Listen("tcp", "0.0.0.0:6000")
ctx, cancel := context.WithTimeout(context.Background(),
    10000*time.Millisecond)

Затем создайте такое соединение:

connection, err = grpc.DialContext(ctx, server2Address,
grpc.WithInsecure(), grpc.WithBlock())

Перед окончательной отправкой сообщения конечной точке на сервере B, которая пытается прочитать IP-адрес входящего соединения сервера A.

info, _ := peer.FromContext(ctx)
fmt.Printf(info.Addr.String()) // Returns a random port, NOT 6000,

Однако результирующий порт, напечатанный сервером B, является случайным, например 62056, а не 6000, как предполагалось. Я предполагаю, что на сервере A GRPC набирает номер со случайного порта — можно ли заставить GRPC набирать номер с порта 6000, а не со случайного порта?

Почему вас волнует номер порта на стороне клиента? Какую более серьезную проблему вы пытаетесь здесь решить?   —  person JTApps    schedule 30.07.2019

Сервер A знает адрес и порт сервера B, но не знает обратного. Каким-то образом мне нужно сообщить серверу B адрес и порт сервера A, чтобы сервер B мог в будущем связываться с сервером A. Итак, я пытаюсь очистить эту информацию из контекста, предоставляемого входящим сообщением от сервера A до Сервер B, однако, номер порта неточный, поэтому этот пост.   —  person JTApps    schedule 30.07.2019

почему бы не разместить службу gRPC на сервере A на хорошо известном порту, чтобы сервер B мог отвечать напрямую? Вы пытаетесь сделать это для обработки конкретной транзакции и вам нужно поддерживать состояние транзакции? Если это так, я бы использовал обмен токенами, а не какой-то потенциально сложный канал связи.   —  person JTApps    schedule 30.07.2019

См. также:  Невозможно развернуть Go в Oracle Cloud Function с помощью Cloud Shell
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 1
  1. JTApps

    Вы можете указать исходный порт следующим образом:

    cc, err := grpc.Dial("127.0.0.1:6001", grpc.WithInsecure(),
        grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
            dst, err := net.ResolveTCPAddr("tcp", addr)
            if err != nil {
                return nil, err
            }
            src := &net.TCPAddr{
                IP:   net.ParseIP("127.0.0.1"),
                Port: 6000,
            }
            return net.DialTCP("tcp", src, dst)
        }))
    

    Однако, если ваш сервер прослушивает тот же порт, это приведет к ошибке:

    panic: dial tcp 127.0.0.1:6000->127.0.0.1:6001: bind: address already in use
    

    Другой подход — передать адрес как метаданные. На клиенте вы делаете:

    ctx := context.Background()
    ctx = metadata.NewOutgoingContext(ctx, metadata.Pairs("address", "127.0.0.1:6000"))
    res, err := grpc_health_v1.NewHealthClient(cc).Check(ctx, &grpc_health_v1.HealthCheckRequest{
        Service: "test",
    })
    

    И на сервере:

    func (s *server) Check(ctx context.Context, req *grpc_health_v1.HealthCheckRequest) (*grpc_health_v1.HealthCheckResponse, error) {
        if md, ok := metadata.FromIncomingContext(ctx); ok {
            addr := md.Get("address")
            // addr == "127.0.0.1:6000"
        }
    
        return &grpc_health_v1.HealthCheckResponse{
            Status: grpc_health_v1.HealthCheckResponse_SERVING,
        }, nil
    }
    

    И третий подход — использовать потоковую передачу.

    Здравствуйте. отлично! Но … как мне указать исходный порт на канале java-client = ManagedChannelBuilder.forAddress (host, port) .build (); person JTApps; 21.12.2019

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: