• Go使用ProtocolBuffers构建高性能的API服务


    仓库

    下面设计思路与实现考虑:

    误区

    restful api VS protobuf api

    • restful api使用http的POST/GET/PUT/DELETE, uri, body实现资源的CRUD操作!
    • protobuf api使用grpc, http(post), websocket实现资源的CRUD操作!

    二者是完全不同二套API方案! 尝试用protobuf api去实现restful api会觉得很别扭! 真的相当别扭!
    但protobuf api的不足就是对文件上传/下载的支持! 而这也是目前最需要解决的问题!

    纠正

    • 目前的grpc, post, get的方式是没有问题的!

    • 不要动态检查,

      • 通过+http-form/+http-file明确指定静态代码生成规则也是没有问题的!
      swith ContentType {
          case ""   
      }    
      

      如果是application/x-www-form-urlencoded或者multipart/form-data则根据request FormValues()来获取Request的值.

      如果是application/json(默认), 则采用json的解析方式!

      但这个步骤不应在request时动态解析,否则会浪费性能!

      • 通过+http-file的编译指令实际是将字段名作为值赋到字段中! 此后通过
        protoapi.FormFile(ctx, field)来获取相关的值!

      • 通过+http-path指定相应的uri

    • 对于Get是用于websocket还是普通的get

      • 做法1: 明确添加+http-wbsk. 因为Websocket的接口不会经常打开! 没有哪个APP会常年打开几十个websocket链接连着后台!
    • 仍然需要PackagePrefix/PackageSuffix,ServicePrefix/ServiceSuffix,MethodPrefix/MethodSuffix统一定制整套扩展实现!

    效果:

    syntax = "proto3";
    
    package hello;
    
    // +http-form #按照form表单而非json内容解析Request
    message UploadReq {
        // +http-file #在form-file中会有一个以"test_file"命名的文件!
        string test_file = 1;
    }
    
    message UploadRsp {
        string status = 1;
    }
    
    service Greeter {
        // +http-wbsk
        // +http-path /demo/upload #默认是 /hello/greeter/upload
        rpc Upload(UploadReq) returns (UploadRsp);
    }
    
    • 默认每个service.method会暴露grpc/http(POST/GET)二种接口, 可以通过protoapi进行更细设置,就像PackagePrefix/PackageSuffix, ServicePrefix/ServiceSuffix, MethodPrefix/MethodSuffix等, 其实可以更深地抽象为一个HttpPathGenerator接口
    type HttpPathGenerator interface{
        Generate(package, service, method, httpPath string) string
    }
    其中会有一个全局的defaultHttpPathGenerator(c *Config) 生成根据prefic/suffix来创建http-path的对象!
    
    • 对于uri或query的参数是否去匹配

      • +http-form表示从form表单提取字段值.
      • +http-urls表示从path路径提取字段值,包括query!
    • 对于全部的build constraints

      • 用于message的: +http-form, +http-json
      • 用于field的: +http-file
      • 用于method的: +http-path, +http-get/+http-get-wbsk

      这些都是http标签, 能否把http-前缀去掉:

      • +form(form+query), +json
      • 解析path,如果带:param等参数,自动加入到参数的解析里面!
    • 正常地

      • 生成grpc
      • 生成http(post), http(get)

      如果标记(wbsk)是生成websocket代替掉get, 能否

    • 换一种思路:

      • 生成grpc
      • 生成post

      • 生成wbsk
      • 生成get

      无论是wbsk或者get都不是常用的方式, 指定+get websocket

      从可读性来看, 还是带上http-前缀比较明确意思!

    汇总

    默认行为

    • 默认service.method暴露grpc, post接口
    • 默认message是application/json解析
    • 默认protoapi不开启Grpc或Http接口, 需要配置OpenGrpc(switch int)或OpenHttp(switch int)

    扩展行为

    • http-form/http-file, http-json: body的内容是form而不是json, 如果是form则包括query部分(使用http.Request.FormValue(key))来提取值! 不论是form还是json都会解析uri判断是否带有:param,如果有的话, 则会自动添加相应的解析部分! 另外提供protoapi.FormFile(context, field)辅助获取上传的文件!

    • http-path用于指定uri(支持:param), 要在生成的_http.pb.go加上protoapi的相关包引用!

      • http-get或http-get-wbsk用于打开Get请求! 默认情况开启http-post足够应付大多数请求场景! 但有时需要支持主页或下载(Get), 或者websocket的情况, 就需要把get开启! 另外提供protoapi.DownFile(context, name, reader). 需要调用者负责关闭文件句柄或者其他! 但是需要注意, 调用protoapi.DownFile()后会关闭http.ResponseWriter,不再往里再写任何操作!
    • 上传与下载文件是特殊行为, 使用受特殊限制!

  • 相关阅读:
    代码比较工具TexDiff
    如何使用opengl的扩展
    在opengl里如何给cg程序设置参数
    static function
    book gpu
    aistudio
    基于Pytorch实现的声纹识别模型
    pytorch使用google UISRNN算法识别出每个人的声音(以92%的准确率 google/uisrnn)
    easydl
    出现“adb不是内部或外部命令,也不是可运行的程序或批量文件。”
  • 原文地址:https://www.cnblogs.com/zolo/p/14031806.html
Copyright © 2020-2023  润新知