What's new in dubbo-go-pixiu v0.6.0

語言: CN / TW / HK

pixiu 0.6.0 雖然艱辛,但在社區小夥伴的努力下發布了。這個版本不止有常規社區功能,還有很多功能特性是來源於ASoC-2022 Alibaba Summer of Code,OSPP(中科院軟件所[開源軟件供應鏈點亮計劃]) , GSoC(Google Summer of Code) 提案內容。

New Features In v0.6.0

nacos config

背景:pixiu 的配置,啟動配置項(conf.yaml),日誌配置(log.yml)均是從本地文件加載,沒有接入動態配置中心的能力,而日常生產環境中,配置通過配置中心集中下發管理是更為靈活和安全的方式之一。

動態配置下發的場景還有很多擴展,接入的組件也因公司的選型有所不同,當前我們主要考慮接入 nacos 配置中心。

注:在設計上可以考慮,如何在二次開發場景下更為“標準、安全、簡單”的接入其他配置中心。

Pixiu 啟動時從配置中心Nacos 拉取配置 conf.yaml 數據


pixiu.conf的配置不用配置static_resources,需要配置config-center和nacos:

config-center:
  type: nacos
  enable: true
nacos:
  server-configs:
    - ip_addr: "127.0.0.1"
      port: 8848
  client-config:
    username: nacos
    password: nacos

原來我們熟悉pixiu.conf配置內容放到了nacos中:

static_resources:
  listeners:
    - name: "net/http"
      protocol_type: "HTTP"
      address:
        socket_address:
          address: "0.0.0.0"
          port: 8881
      filter_chains:
          filters:
            - name: dgp.filter.httpconnectionmanager
              config:
                route_config:
                  routes:
                    - match:
                        prefix: "*"
                http_filters:
                  - name: dgp.filter.http.dubboproxy
                    config:
                      dubboProxyConfig:
                        auto_resolve: true
                        registries:
                          "zookeeper":
                            protocol: "zookeeper"
                            timeout: "3s"
                            address: "127.0.0.1:2181"
                            username: ""
                            password: ""
                        timeout_config:
                          connect_timeout: 5s
                          request_timeout: 5s

                server_name: "test_http_dubbo"
                generate_request_id: false
      config:
        idle_timeout: 5s
        read_timeout: 5s
        write_timeout: 5s
  shutdown_config:
    timeout: "60s"
    step_timeout: "10s"
    reject_policy: "immediacy"

更詳細的配置參考samples: https://github.com/apache/dubbo-go-pixiu-samples/tree/main/dubbogo/simple/farconfnacos

nacos配置支持還需要進一步完善的功能:

  • 動態託管/下發用户自定義配置
  • 動態下發Pixiu配置

OSPP: Traffic Distribution

流量分發提供兩種策略,基於 Request Header 和服務權重的流量切分。

canary-by-header

canary-by-header是要匹配的 Request Header 的值,當 Request Header 設置此值時,它將被路由到相應的cluster(cluster中綁定canary-by-header鍵值)。當請求不包含這一 Request Header 或 Header 值不匹配時,請求不會被髮送到Canary版本,該策略適用於藍綠髮布以及A/B測試

canary-weight

這種策略適用於金絲雀部署,權重範圍 0 - 100 按百分比將請求路由到指定的服務。權重為 0 意味着該金絲雀規則不會向 Canary 服務發送任何請求;權重為 100 意味着所有請求都將被髮送到 Canary。

Add Graceful Shutdown

通過graceful shutdown 能力,在進程獲得系統型號:SIGINT, SIGKILL, SIGTERM信號時執行graceful shutdown過程:拒絕新的請求;等待處理中請求完成直到timeout.

static_resources:
	.......
	.......
  shutdown_config:
    timeout: "60s"
    step_timeout: "10s"
    reject_policy: "immediacy"

配置方式參考: https://github.com/apache/dubbo-go-pixiu-samples/tree/main/shutdown

WASM Plugin for Pixiu

Pixiu 支持 WASM 插件機制,實現http fitler。

PIxiu與WASM擴展代碼交互採取 Proxy-Wasm 規範,該規範是開源社區針對「網絡代理場景」設計的一套 ABI 規範,採用該規範能讓PIxiu複用社區既有的WASM擴展。

WASM原則上應該支持多種語言,這裏以Go語言為例,最終通過tinygo編譯成wasm文件。如果要實現我們的擴展WASM程序,需要按以下模版進行編碼實現:

package main

import (
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
)

func main() {
    proxywasm.SetNewHttpContext(newHttpContext)
}

type myHttpContext struct {
    // you must embed the default context so that you need not to re-implement all the methods by yourself
    proxywasm.DefaultHttpContext
    contextID uint32
}

func newHttpContext(rootContextID, contextID uint32) proxywasm.HttpContext {
    return &myHttpContext{contextID: contextID}
}

// override
func (ctx *myHttpContext) OnHttpRequestHeaders(numHeaders int, endOfStream bool) types.Action {

    return types.ActionContinue
}

deploy pixiu as dubbo service ingress gateway in k8s istio

當dubbo部署istio + k8s環境中,pixiu可以作為dubbo provider的ingress gateway,接收dubbo/triple/http的流量,並將請求轉發到dubbo provider中。

samples: https://github.com/apache/dubbo-go-pixiu-samples/tree/main/xds/dubbo-go-istio

ASoC 2022: Pixiu Metrics Implementation

Pixiu Metrics提供四個prometheus運行指標:

var reqCnt = &Metric{
	ID:          "reqCnt",
	Name:        "requests_total",
	Description: "How many HTTP requests processed, partitioned by status code and HTTP method.",
	Type:        "counter_vec",
	Args:        []string{"code", "method", "host", "url"},
}

var reqDur = &Metric{
	ID:          "reqDur",
	Name:        "request_duration_seconds",
	Description: "The HTTP request latencies in seconds.",
	Args:        []string{"code", "method", "url"},
	Type:        "histogram_vec",
	Buckets:     reqDurBuckets,
}

var resSz = &Metric{
	ID:          "resSz",
	Name:        "response_size_bytes",
	Description: "The HTTP response sizes in bytes.",
	Args:        []string{"code", "method", "url"},
	Type:        "histogram_vec",
	Buckets:     resSzBuckets,
}

var reqSz = &Metric{
	ID:          "reqSz",
	Name:        "request_size_bytes",
	Description: "The HTTP request sizes in bytes.",
	Args:        []string{"code", "method", "url"},
	Type:        "histogram_vec",
	Buckets:     reqSzBuckets,
}

var standardMetrics = []*Metric{
	reqCnt,
	reqDur,
	resSz,
	reqSz,
}

config配置http_filters: dgp.filter.http.prometheusmetric:

static_resources:
  listeners:
    - name: "net/http"
      protocol_type: "HTTP"
      address:
        socket_address:
          address: "0.0.0.0"
          port: 8888
      filter_chains:
        filters:
          - name: dgp.filter.httpconnectionmanager
            config:
              route_config:
                routes:
                  - match:
                      prefix: /health
                    route:
                      cluster: user
                      cluster_not_found_response_code: 505
                  - match:
                      prefix: /user
                    route:
                      cluster: user
                      cluster_not_found_response_code: 505
                  - match:
                      prefix: /prefix
                    route:
                      cluster: user
                      cluster_not_found_response_code: 505
              http_filters:
                - name: dgp.filter.http.prometheusmetric
                  metric_collect_rules:
                    metric_path: "/metrics"
                    push_gateway_url: "http://127.0.0.1:9091"
                    counter_push: true
                    push_interval_threshold: 3
                    push_job_name: "prometheus"
                - name: dgp.filter.http.httpproxy                    
      config:
        idle_timeout: 5s
        read_timeout: 5s
        write_timeout: 5s
  clusters:
    - name: "user"
      lb_policy: "lb"
      endpoints:
        - id: 1
          socket_address:
            address: 127.0.0.1
            port: 1314
      health_checks:
        - protocol: "tcp"
          timeout: 1s
          interval: 2s
          healthy_threshold: 4
          unhealthy_threshold: 4
  shutdown_config:
    timeout: "60s"
    step_timeout: "10s"
    reject_policy: "immediacy"

sample參考: https://github.com/apache/dubbo-go-pixiu-samples/tree/main/dubbogo/simple/prometheus

feat:consistent hashing

為cluster 提供基於一致性hash的請求負載算法;

clusters:
  - name: "test_dubbo"
    lb_policy: "ConsistentHashing"
    registries:
      "zookeeper":
        timeout: "3s"
        address: "127.0.0.1:2181"
        username: ""
        password: ""

Enhancement in v0.6.0

Remove "Types" on Http to dubbo proxy

在通過http調用dubbo服務的場景中,v0.6.0以前版本需要再請求中包含"types": ...., 來描述dubbo parameters的結構描述,示例 :{"types":"string"....

func TestPost1(t *testing.T) {
    url := "http://localhost:8883/UserService/com.dubbogo.pixiu.UserService/GetUserByName"
    data := "{"types":"string","values":"tc"}"
    client := &http.Client{Timeout: 5 * time.Second}
    req, err := http.NewRequest("POST", url, strings.NewReader(data))
    req.Header.Set("x-dubbo-http1.1-dubbo-version", "1.0.0")
    req.Header.Set("x-dubbo-service-protocol", "dubbo")
    req.Header.Set("x-dubbo-service-version", "1.0.0")
    req.Header.Set("x-dubbo-service-group", "test")
    assert.NoError(t, err)
    req.Header.Add("Content-Type", "application/json")
    resp, err := client.Do(req)
    assert.NoError(t, err)
    assert.NotNil(t, resp)
    assert.Equal(t, 200, resp.StatusCode)
    s, _ := ioutil.ReadAll(resp.Body)
    assert.True(t, strings.Contains(string(s), "0001"))
}

改進之後data中不需要types數據。

sample 代碼: https://github.com/apache/dubbo-go-pixiu-samples/blob/main/dubbogo/simple/direct/test/pixiu_test.go

ASoC 2002: Optimization of Pixiu timeout feature

dgp.filter.http.dubboproxy 支持超時配置:

..........
.........
- name: dgp.filter.http.dubboproxy
  config:
    dubboProxyConfig:
      registries:
        "zookeeper":
          protocol: "zookeeper"
          timeout: "3s"
          address: "127.0.0.1:2181"
          username: ""
          password: ""
      timeout_config:
        connect_timeout: 5s
        request_timeout: 5s

歡迎釘釘掃碼加入 dubbogo 社區釘釘羣【釘釘羣號 23331795】進行交流。