基于Nginx和Cookie的灰度系统

kyaa111 5月前 ⋅ 234 阅读
import (
	"flag"
	"fmt"
	"net/http"
)

func main() {
	port := flag.Int("port", 4444, "HTTP server port")
	content := flag.String("content", "", "content")
	flag.Parse()

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		htmlContent := "<!DOCTYPE html><html><head><title>Test Page</title></head><body><h1>Hello, this is a " + *content + "!</h1></body></html>"
		w.Header().Set("Content-Type", "text/html")
		w.Write([]byte(htmlContent))
	})

	addr := fmt.Sprintf(":%d", *port)
	fmt.Printf("Server is running on http://localhost%s\n", addr)
	err := http.ListenAndServe(addr, nil)
	if err != nil {
		fmt.Printf("Error starting server: %s\n", err)
	}
}

go build server.go

改改参数, 启动两个进程

nohup ./server -port 4445 -content test1 > /dev/null 2>&1 &

修改nginx配置

upstream go-server1 {
    server 127.0.0.1:4445;
}

upstream go-server2 {
    server 127.0.0.1:4446;
}

upstream default {
    server 127.0.0.1:4445;
}

server {
    listen       80;
    server_name  localhost;

    set $group "default";

    if ($http_cookie ~* "version=1.0") {
        set $group go-server1;
    }

    if ($http_cookie ~* "version=2.0") {
        set $group go-server2;
    }

    location / {
        proxy_pass http://$group;
    }
}

实现效果

root@localhost:/usr/local/nginx# curl -H "Cookie: version=1.0" localhost
<!DOCTYPE html><html><head><title>Test Page</title></head><body><h1>Hello, this is a test1!</h1></body></html>

root@localhost:/usr/local/nginx# curl -H "Cookie: version=2.0" localhost
<!DOCTYPE html><html><head><title>Test Page</title></head><body><h1>Hello, this is a test2!</h1></body></html>

这样,我们就实现了灰度的功能

配合灰度配置系统, 进行流量染色, 即可实现完整的灰度发布.

流量染色可以是后端代码处理, 也可以是独立的中间件处理

这里以代码处理示例

修改server.go代码如下

package main

import (
    "flag"
    "fmt"
    "math/rand"
    "net/http"
    "time"
)

func main() {
    rand.Seed(time.Now().UnixNano())

    port := flag.Int("port", 4444, "HTTP server port")
    content := flag.String("content", "", "content")
    flag.Parse()

    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        htmlContent := "<!DOCTYPE html><html><head><title>Test Page</title></head><body><h1>Hello, this is a " + *content + "!</h1></body></html>"
        random := rand.Intn(10)
        if random < 2 {
            cookie := http.Cookie{
                Name:  "version",
                Value: "2.0",
            }
            http.SetCookie(w, &cookie)
        }
        w.Header().Set("Content-Type", "text/html")
        w.Write([]byte(htmlContent))
    })

    addr := fmt.Sprintf(":%d", *port)
    fmt.Printf("Server is running on http://localhost%s\n", addr)
    err := http.ListenAndServe(addr, nil)
    if err != nil {
        fmt.Printf("Error starting server: %s\n", err)
    }
}

在postman中发起调用, 请求几次后即可看到转发到了2.0

灰度系统=标记+染色