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: truenacos:  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 mainimport (    "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}}// overridefunc (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