Skip to content

Latest commit

 

History

History
171 lines (139 loc) · 5.27 KB

2.6.Websocket.md

File metadata and controls

171 lines (139 loc) · 5.27 KB

WebSocket

Background

  • Reverse proxy is one of most popular features of Easegress and it's suitable for many production and development scenarios.

  • In reversed proxy use cases, WebSocket is a widely used protocol for a full-duplex communication solution between client and server. WebSocket relies on TCP.[1]

  • Many reverse proxy support WebSocket,e.g., NGINX[2], Traefik, and so on.

Design

  • The WebSocketProxy is a filter of Easegress, and can be put into a pipeline.
  • Easegress uses nhooyr.io/websocket to implement WebSocketProxy filter.
  1. Spec
  • Pipeline with a WebSocketProxy filter:
name: websocket-pipeline
kind: Pipeline

flow:
- filter: wsproxy

filters:
- kind: WebSocketProxy
  name: wsproxy
  defaultOrigin: http://127.0.0.1/hello
  pools:
  - servers:
    - url: ws://127.0.0.1:12345
      # keepHost: true, the `Host` will be the same as the original request
      # If the backend is a load balancer, it would prove to be highly beneficial
      keepHost: true
    - url: ws://127.0.0.1:9095
    - url: ws://127.0.0.1:9096
    - url: ws://127.0.0.1:9097
    loadBalance:
      policy: roundRobin
    # the max number of bytes to read for a single message in 
    # client/server connection.
    # default is 32769, set -1 to disable limit.
    clientMaxMsgSize: 32769
    serverMaxMsgSize: 32769
  • HTTPServer to route traffic to the websocket-pipeline:
name: demo-server
kind: HTTPServer
port: 8080
rules:
- paths:
  - path: /ws
    clientMaxBodySize: -1          # REQUIRED!
    backend: websocket-pipeline

Note: clientMaxBodySize must be -1.

  1. Request sequence

    +--------------+                +--------------+                +--------------+  
    |              |  1             |              |   2            |              | 
    |   client     +--------------->|  Easegress   +--------------->|  websocket   |
    |              |<---------------+              |<---------------+  backend     | 
    |              |  4             |              |   3            |              |
    +--------------+                +--------------+                +--------------+
    
  2. Headers

We copy all headers from your HTTP request to websocket backend, except ones used by websocket package to build connection. Based on [3], we also add X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Proto to http headers that send to websocket backend.

note: websocket use Upgrade, Connection, Sec-Websocket-Key, Sec-Websocket-Version, Sec-Websocket-Extensions and Sec-Websocket-Protocol in http headers to set connection.

Health Check

Health Check

Perform a health check on the servers in the pool. If a server fails the check, it will be marked as unhealthy, and requests will be rerouted to other healthy servers until it regains health. Health check for websocket proxy contains both http way or websocket way. The HTTP check involves a request-response evaluation similar to a Proxy filter. In the WebSocket method, a successful connection yields a 101 status code. Additional headers can be set and evaluated in both methods. If you send both two ways of health check, then a server passes both HTTP and WebSocket health checks, it will be considered healthy.

More details in WebSocketProxy.

kind: WebSocketProxy
name: proxy-example-1
pools:
- servers:
  - url: ws://127.0.0.1:9095
  - url: ws://127.0.0.1:9096
  - url: ws://127.0.0.1:9097
  healthCheck:
    # interval between health checks (default: 60s)
    interval: 60s
    # timeout for health check response (default: 3s)
    timeout: 3s
    # fail threshold to mark server as unhealthy (default: 1)
    fails: 1
    # success threshold to mark server as healthy (default: 1)
    pass: 1

    ws:
      # health check request port (defaults to server's port, e.g., 9095)
      port: 10080
      # uri for health check
      uri: /health/ws
      # http request headers for health check
      headers:
        X-Health-Check: easegress

      # response validation criteria (default: 101 Switching Protocols)
      match:
        # acceptable status code ranges 
        statusCodes:
        - [101, 101] # 101
        # response header validation
        # name is header key.
        # value is header value, can be empty. 
        # type is type of value, can be "exact" or "regexp".
        headers:
        - name: X-Status
          value: healthy
          type: exact
    http:
      uri: /health

Example

  1. Send request

    curl --include \
        --no-buffer \
        --header "Connection: Upgrade" \
        --header "Upgrade: websocket" \
        --header "Host: 127.0.0.1:10020" \
        --header "Sec-WebSocket-Key: your-key-here" \
        --header "Sec-WebSocket-Version: 13" \
        http://127.0.0.1:8080/
  2. This request to Easegress will be forwarded to websocket backend ws://127.0.0.1:12345.

References

  1. https://datatracker.ietf.org/doc/html/rfc6455
  2. https://www.nginx.com/blog/websocket-nginx/
  3. https://docs.oracle.com/en-us/iaas/Content/Balance/Reference/httpheaders.htm