• GRPC头测试记录


    GRPC头记录

    http://nodejs.cn/api/http2/note_on_authority_and_host.html
    https://cloud.tencent.com/developer/section/1189948
    https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/User-Agent

    Header说明

    :authority

    个人理解:可视为host,表示服务的IP+Port

    HTTP/2 要求请求具有 :authority 伪标头或 host 标头。 当直接构建 HTTP/2 请求时首选 :authority,从 HTTP/1 转换时首选 host(例如在代理中)。
    
    如果 :authority 不存在,则兼容性 API 将回退到 host。 有关详细信息,请参阅 request.authority。 但是,如果不使用兼容性 API(或直接使用 req.headers),则需要自己实现任何回退行为。
    
    ":authority" 伪头字段包含目标 URI 的部分权限([RFC3986],第 3.2 节)。权限不得包含 "http" 或 "https" scheme URI 的已弃用 "userinfo" 子组件。为了确保可以准确地再现 HTTP/1.1请求行,当从具有源或星号形式的请求目标的 HTTP/1.1 请求进行转换时,必须省略该伪头字段(参见[RFC7230],第 5.3 节)。直接生成 HTTP/2 请求的客户端应该使用 ":authority" 伪头字段而不是 Host 头字段。将 HTTP/2 请求转换为 HTTP/1.1 的网络中间件必须通过复制 ":authority" 伪头字段的值来创建 Host 头字段(如果请求中不存在的话)。
    

    user-agent

    User-Agent 首部包含了一个特征字符串,用来让网络协议的对端来识别发起请求的用户代理软件的应用类型、操作系统、软件开发商以及版本号。

    记录说明

    • 192.168.10.173 PC1-IP
    • 192.168.10.96 PC2-IP
    • 192.168.10.152 kong网关-IP
    • c++ 服务在173运行
    • golang服务在96运行
    • 标签为服务,子标签为客户端

    C++ Service

    c++直接访问

    Client metadata: 
    Header key: user-agent, value: grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)
    

    golang访问

    Client metadata: 
    Header key: user-agent, value: grpc-go/1.46.2
    

    kong网关-c++

    Client metadata: 
    Header key: user-agent, value: grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)
    Header key: x-forwarded-for, value: 192.168.10.173
    Header key: x-forwarded-host, value: 192.168.10.152
    Header key: x-forwarded-path, value: /hello.HelloService/SayHello
    Header key: x-forwarded-port, value: 8508
    Header key: x-forwarded-proto, value: http
    Header key: x-real-ip, value: 192.168.10.173
    

    kong网关-golang

    Client metadata: 
    Header key: user-agent, value: grpc-go/1.46.2
    Header key: x-forwarded-for, value: 192.168.10.96
    Header key: x-forwarded-host, value: 192.168.10.152
    Header key: x-forwarded-path, value: /hello.HelloService/SayHello
    Header key: x-forwarded-port, value: 8508
    Header key: x-forwarded-proto, value: http
    Header key: x-real-ip, value: 192.168.10.96
    

    kong网关-grpc_web

    Client metadata: 
    Header key: accept, value: application/grpc-web-text
    Header key: accept-encoding, value: gzip, deflate
    Header key: accept-language, value: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
    Header key: content-length, value: 9
    Header key: origin, value: http://192.168.10.173:8080
    Header key: referer, value: http://192.168.10.173:8080/
    Header key: user-agent, value: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53
    Header key: x-forwarded-for, value: 192.168.10.96
    Header key: x-forwarded-host, value: 192.168.10.152
    Header key: x-forwarded-path, value: /hello.HelloService/SayHello
    Header key: x-forwarded-port, value: 8509
    Header key: x-forwarded-prefix, value: /hello
    Header key: x-forwarded-proto, value: http
    Header key: x-grpc-web, value: 1
    Header key: x-real-ip, value: 192.168.10.96
    Header key: x-user-agent, value: grpc-web-javascript/0.1
    

    Golang Service

    c++ 直接访问

    Client metadata:
    :authority  ::  [192.168.10.96:8503]
    content-type  ::  [application/grpc]
    grpc-accept-encoding  ::  [identity, deflate, gzip]
    user-agent  ::  [grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)]
    

    golang 访问

    Client metadata:
    :authority  ::  [192.168.10.96:8503]
    content-type  ::  [application/grpc]
    user-agent  ::  [grpc-go/1.46.2]
    

    kong网关- golang

    Client metadata:
    x-forwarded-path  ::  [/hello.HelloService/SayHello]
    x-real-ip  ::  [192.168.10.96]
    x-forwarded-for  ::  [192.168.10.96]
    x-forwarded-port  ::  [8508]
    x-forwarded-host  ::  [192.168.10.152]
    content-type  ::  [application/grpc]
    user-agent  ::  [grpc-go/1.46.2]
    :authority  ::  [192.168.10.96:8503]
    x-forwarded-proto  ::  [http]
    

    kong网关- c++

    Client metadata:
    x-forwarded-for  ::  [192.168.10.173]
    content-type  ::  [application/grpc]
    grpc-accept-encoding  ::  [identity, deflate, gzip]
    x-forwarded-port  ::  [8508]
    x-forwarded-host  ::  [192.168.10.152]
    x-real-ip  ::  [192.168.10.173]
    x-forwarded-path  ::  [/hello.HelloService/SayHello]
    user-agent  ::  [grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)]
    :authority  ::  [192.168.10.96:8503]
    x-forwarded-proto  ::  [http]
    

    kong网关- grpc_web

    Client metadata:
    referer  ::  [http://192.168.10.173:8080/]
    x-forwarded-for  ::  [192.168.10.96]
    x-forwarded-path  ::  [/hello.HelloService/SayHello]
    accept-language  ::  [zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6]
    content-length  ::  [9]
    x-forwarded-port  ::  [8509]
    accept  ::  [application/grpc-web-text]
    x-grpc-web  ::  [1]
    x-real-ip  ::  [192.168.10.96]
    x-user-agent  ::  [grpc-web-javascript/0.1]
    accept-encoding  ::  [gzip, deflate]
    x-forwarded-prefix  ::  [/hello]
    user-agent  ::  [Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53]
    content-type  ::  [application/grpc]
    origin  ::  [http://192.168.10.173:8080]
    x-forwarded-host  ::  [192.168.10.152]
    :authority  ::  [192.168.10.96:8503]
    x-forwarded-proto  ::  [http]
    

    总结

    获取客户端IP

    C++ 服务端

    C++暂时未实现如何从**context**`获取客户端IP`
    
    服务端如果有需要,建议和客户端约定一个**Key**作为`header`
    

    Go 服务端

    虽然Go在直接访问时,无法从header中读取到客户端IP相关,但通过google.golang.org/grpc/peer包获取到客户端IP

    p, _ := peer.FromContext(ctx)
    fmt.Println(p.Addr.String(),"  ",p.Addr.Network())
    
    Addr()为IP,NetWork为传输方式(tcp/udp/..)
    

    MetaData

    Go metadata

        ## clinet code
        ctx := context.Background()
        md := metadata.New(map[string]string{"demo": "go client"})
        newCtx2 := metadata.NewOutgoingContext(ctx, md)
    
     - go service:
        Client metadata:
        user-agent  ::  [grpc-go/1.46.2]
        demo  ::  [go client]
        :authority  ::  [192.168.10.96:8503]
        content-type  ::  [application/grpc]
    
     - c++ service:
        Client metadata: 
        Header key: go, value: programming
        Header key: tour, value: book
        Header key: user-agent, value: grpc-go/1.46.2
    

    C++ metadata

        ## clinet code
        grpc::ClientContext context;
        context.AddMetadata("demo", "c++ client");
    
      - go:
        Client metadata:
        :authority  ::  [192.168.10.96:8503]
        content-type  ::  [application/grpc]
        grpc-accept-encoding  ::  [identity, deflate, gzip]
        user-agent  ::  [grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)]
        demo  ::  [c++ client]
        
      - c++:
        Client metadata: 
        Header key: demo, value: c++ client
        Header key: user-agent, value: grpc-c++/1.46.0-dev grpc-c/23.0.0 (linux; chttp2)
    

    测试程序

    proto

    syntax = "proto2";
    
    package hello;
    option go_package = "./hello";
    service HelloService {
        rpc SayHello(HelloRequest) returns (HelloResponse);
        rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
        rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
        rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
    }
    
    message HelloRequest {
        optional string greeting = 1;
    }
    
    message HelloResponse {
        required string reply = 1;
    }
    

    Go

    /*
     GRPC 服务端
     */
    package main
    
    import (
    	"context"
    	pb "demo_hello/proto/hello"
    	"fmt"
    	"google.golang.org/grpc"
    	"google.golang.org/grpc/metadata"
    	"log"
    	"net"
    )
    
    type Server struct {
    	pb.UnimplementedHelloServiceServer
    }
    
    func (S *Server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloResponse, error) {
    	res := "this is 96"
    	fmt.Println("Client metadata:")
    	if headers, ok := metadata.FromIncomingContext(ctx); ok {
    		for head, val := range headers {
    			fmt.Println(head, " :: ", val)
    		}
    	}
    	return &pb.HelloResponse{Reply: &res}, nil
    }
    func main() {
    	lis, err := net.Listen("tcp", "0.0.0.0:8503")
    	if err != nil {
    		log.Fatalf("failed listen: %v", err)
    	}
    	s := grpc.NewServer()
    	pb.RegisterHelloServiceServer(s, &Server{})
    	log.Printf("Server listen:%v", lis.Addr())
    	if err := s.Serve(lis); err != nil {
    		log.Fatalf("Failed Server: %v", err)
    	}
    }
    
    
    /*
    	GRPC 客户端
     */
    package main
    
    import (
    	"context"
    	"flag"
    	"google.golang.org/grpc/metadata"
    	"log"
    	"time"
    
    	pb "demo_hello/proto/hello"
    	"google.golang.org/grpc"
    	"google.golang.org/grpc/credentials/insecure"
    )
    
    const (
    	defaultName = "world"
    )
    
    var (
    	addr = flag.String("addr", "192.168.10.96:8503", "the address to connect to")
    )
    
    func main() {
    	flag.Parse()
    	// Set up a connection to the server.
    	conn, err := grpc.Dial(*addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
    	if err != nil {
    		log.Fatalf("did not connect: %v", err)
    	}
    	defer conn.Close()
    	c := pb.NewHelloServiceClient(conn)
    
    	// Contact the server and print out its response.
    	ctx := context.Background()
    	md := metadata.New(map[string]string{"demo": "go client"})
    
    	newCtx2 := metadata.NewOutgoingContext(ctx, md)
    	ctx, cancel := context.WithTimeout(newCtx2, time.Second)
    	defer cancel()
    	name := "ss"
    	r, err := c.SayHello(ctx, &pb.HelloRequest{Greeting: &name})
    	if err != nil {
    		log.Fatalf("could not greet: %v", err)
    	}
    	log.Printf("Greeting: %s", r.GetReply())
    }
    

    C++

    /*
        GRPC server
    */
    #include <iostream>
    #include <memory>
    #include <string>
    
    #include <grpcpp/grpcpp.h>
    
    #ifdef BAZEL_BUILD
    #include "examples/protos/helloworld.grpc.pb.h"
    #else
    #include "hello_world/hello_world.grpc.pb.h"
    #endif
    
    using grpc::Server;
    using grpc::ServerBuilder;
    using grpc::ServerContext;
    using grpc::Status;
    using hello::HelloRequest;
    using hello::HelloResponse;
    using hello::HelloService;
    using Service = hello::HelloService::Service;
    // Logic and data behind the server's behavior.
    class GreeterServiceImpl final : public Service {
        Status SayHello(ServerContext *context, const HelloRequest *request, hello::HelloResponse *reply) override {
            std::string prefix("Hello ");
    
            // Get the client's initial metadata
            std::cout << "Client metadata: " << std::endl;
            const std::multimap<grpc::string_ref, grpc::string_ref> metadata = context->client_metadata();
            for (auto iter = metadata.begin(); iter != metadata.end(); ++iter) {
                std::cout << "Header key: " << iter->first << ", value: ";
                // Check for binary value
                size_t isbin = iter->first.find("-bin");
                if ((isbin != std::string::npos) && (isbin + 4 == iter->first.size())) {
                    std::cout << std::hex;
                    for (auto c : iter->second) {
                        std::cout << static_cast<unsigned int>(c);
                    }
                    std::cout << std::dec;
                } else {
                    std::cout << iter->second;
                }
                std::cout << std::endl;
            }
    
            reply->set_reply("173");
            return Status::OK;
        }
    };
    
    void RunServer() {
        std::string server_address("0.0.0.0:8503");
        GreeterServiceImpl service;
    
        ServerBuilder builder;
        // Listen on the given address without any authentication mechanism.
        builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
        // Register "service" as the instance through which we'll communicate with
        // clients. In this case it corresponds to an *synchronous* service.
        builder.RegisterService(&service);
        // Finally assemble the server.
        std::unique_ptr<Server> server(builder.BuildAndStart());
        std::cout << "Server listening on " << server_address << std::endl;
    
        // Wait for the server to shutdown. Note that some other thread must be
        // responsible for shutting down the server for this call to ever return.
        server->Wait();
    }
    
    int main(int argc, char **argv) {
        RunServer();
    
        return 0;
    }
    
    /*
        GRPC client
    */
    //
    // Created by mimo on 2022/5/24.
    //
    #include "iostream"
    
    #include "memory"
    
    #include "grpcpp/grpcpp.h"
    #include "hello_world/hello_world.grpc.pb.h"
    
    using namespace std;
    using namespace hello;
    class HelloClient {
    public:
        explicit HelloClient(const std::shared_ptr<grpc::Channel> &channel)
            : stub_(hello::HelloService::NewStub(channel)) {}
    
        void SayHello() {
            grpc::ClientContext context;
            context.AddMetadata("demo", "c++ client");
            HelloRequest request;
            HelloResponse response;
    
            request.set_greeting("dd");
    
            auto res = stub_->SayHello(&context, request, &response);
            if (!res.ok()) {
                std::cout << "Failed IsConnected alarm server" << std::endl;
                return;
            }
            std::cout << response.reply();
        }
    
    private:
        std::unique_ptr<hello::HelloService::Stub> stub_;
    };
    
    int main(){
        HelloClient client(grpc::CreateChannel("192.168.10.96:8503", grpc::InsecureChannelCredentials()));
        client.SayHello();
        return 0;
    }
    
  • 相关阅读:
    Linux时间同步
    idea中创建多module时,找不到创建class文件问题
    Docker中安装Redis并设置外网可访问
    Docker简介与安装
    RabbitMQ基础篇
    git emoji
    RabbitMQ安装
    ActiveMQ
    消息中间件介绍
    IDEA使用GsonFormat完成JSON和JavaBean之间的转换
  • 原文地址:https://www.cnblogs.com/guapilsh/p/16327173.html
Copyright © 2020-2023  润新知