• 网关
    • 部署模型
      • Gateway
      • Agent
    • http协议
    • 例子

    网关

    Gateway 为 rpcx services 提供了 http 网关服务.

    你可以使用你熟悉的编程语言, 比如Java、Python、C#、Node.js、Php、C\C++、Rust等等来调用 rpcx 服务。查看一些编程语言实现的例子 。

    这意味着,你可以不用实现 rpcx的协议,而是使用熟悉的 http 访问方式调用 rpcx 服务, 设置用curlwget等命令行工具。

    部署模型

    使用网关程序有两种部署模型: GatewayAgent

    Gateway

    Gateway - 图1

    你可以部署为网关模式。网关程序运行在独立的机器上,所有的client都将http请求发送给gateway, gateway负责将请求转换成rpcx的请求,并调用相应的rpcx 服务, 它将rpcx 的返回结果转换成http的response, 返回给client。

    你可以部署多台gateway程序, 并可以利用nginx等进行负载均衡。

    Agent

    Gateway - 图2

    你可以将网关程序和1你的client一起部署, agent作为一个后台服务部署在 client机器上。 如果你的机器有多个client, 你只需部署一个agent。

    Client发送 http 请求到本地的agent, 本地的agent将请求转为 rpcx请求,然后转发到相应的 rpcx服务上, 然后将 rpcx的response转换为 http response返回给 client。

    它类似 mesh service的 Sidecar模式, 但是比较好的是, 同一台机器上的client只需一个agent。

    http协议

    你可以使用任意的编程语言来发送http请求,但是需要额外设置一些header (但是不一定设置全部的header, 按需设置):

    • X-RPCX-Version: rpcx 版本
    • X-RPCX-MesssageType: 设置为0,代表请求
    • X-RPCX-Heartbeat: 是否是heartbeat请求, 缺省false
    • X-RPCX-Oneway: 是否是单向请求, 缺省false.
    • X-RPCX-SerializeType: 0 as raw bytes, 1 as JSON, 2 as protobuf, 3 as msgpack
    • X-RPCX-MessageID: 消息id, uint64 类型
    • X-RPCX-ServicePath: service path
    • X-RPCX-ServiceMethod: service method
    • X-RPCX-Meta: 额外的元数据

    对于 http response, 可能会包含一些header:

    • X-RPCX-Version: rpcx 版本
    • X-RPCX-MesssageType: 1 ,代表response
    • X-RPCX-Heartbeat: 是否是heartbeat请求
    • X-RPCX-MessageStatusType: Error 还是正常返回结果
    • X-RPCX-SerializeType: 0 as raw bytes, 1 as JSON, 2 as protobuf, 3 as msgpack
    • X-RPCX-MessageID: 消息id, uint64 类型
    • X-RPCX-ServicePath: service path
    • X-RPCX-ServiceMethod: service method
    • X-RPCX-Meta: extra metadata
    • X-RPCX-ErrorMessage: 错误信息, 如果 X-RPCX-MessageStatusType 是 Error的花

    例子

    下面是Go的一个例子:

    1. package main
    2. import (
    3. "bytes"
    4. "io/ioutil"
    5. "log"
    6. "net/http"
    7. "github.com/rpcx-ecosystem/rpcx-gateway"
    8. "github.com/smallnest/rpcx/codec"
    9. )
    10. type Args struct {
    11. A int
    12. B int
    13. }
    14. type Reply struct {
    15. C int
    16. }
    17. func main() {
    18. cc := &codec.MsgpackCodec{}
    19. // request
    20. args := &Args{
    21. A: 10,
    22. B: 20,
    23. }
    24. data, _ := cc.Encode(args)
    25. req, err := http.NewRequest("POST", "http://127.0.0.1:9981/", bytes.NewReader(data))
    26. if err != nil {
    27. log.Fatal("failed to create request: ", err)
    28. return
    29. }
    30. // set extra headers
    31. h := req.Header
    32. h.Set(gateway.XMessageID, "10000")
    33. h.Set(gateway.XMessageType, "0")
    34. h.Set(gateway.XSerializeType, "3")
    35. h.Set(gateway.XServicePath, "Arith")
    36. h.Set(gateway.XServiceMethod, "Mul")
    37. // send to gateway
    38. res, err := http.DefaultClient.Do(req)
    39. if err != nil {
    40. log.Fatal("failed to call: ", err)
    41. }
    42. defer res.Body.Close()
    43. // handle http response
    44. replyData, err := ioutil.ReadAll(res.Body)
    45. if err != nil {
    46. log.Fatal("failed to read response: ", err)
    47. }
    48. // parse reply
    49. reply := &Reply{}
    50. err = cc.Decode(replyData, reply)
    51. if err != nil {
    52. log.Fatal("failed to decode reply: ", err)
    53. }
    54. log.Printf("%d * %d = %d", args.A, args.B, reply.C)
    55. }

    不能进行双向通讯, 也就是服务端不能主动发送请求给客户端。