配置文件
################################################################
#
# Configuration sample for Traefik v2.
#
# For Traefik v1: https://github.com/traefik/traefik/blob/v1.7/traefik.sample.toml
#
################################################################
################################################################
# Global configuration
################################################################
global:
checkNewVersion: true
sendAnonymousUsage: true
################################################################
# EntryPoints configuration
################################################################
# EntryPoints definition
#
# Optional
#
entryPoints:
#http端口
web:
address: :80
#https端口
websecure:
address: :443
#控制台端口
traefik:
address: :8080
################################################################
# Traefik logs configuration
################################################################
# Traefik logs
# Enabled by default and log to stdout
#
# Optional
#
log:
# Log level
#
# Optional
# Default: "ERROR"
level: DEBUG
# Sets the filepath for the traefik log. If not specified, stdout will be used.
# Intermediate directories are created if necessary.
#
# Optional
# Default: os.Stdout
#
filePath: traefik.log
# Format is either "json" or "common".
#
# Optional
# Default: "common"
#
# format: json
################################################################
# Access logs configuration
################################################################
# Enable access logs
# By default it will write to stdout and produce logs in the textual
# Common Log Format (CLF), extended with additional fields.
#
# Optional
#
#accessLog:
# Sets the file path for the access log. If not specified, stdout will be used.
# Intermediate directories are created if necessary.
#
# Optional
# Default: os.Stdout
#
# filePath: ./log/traefik-access.log
# Format is either "json" or "common".
#
# Optional
# Default: "common"
#
# format: json
################################################################
# API and dashboard configuration
################################################################
# Enable API and dashboard
#
# Optional
#
api:
# Enable the API in insecure mode
#
# Optional
# Default: false
#
insecure: true
# Enabled Dashboard
#
# Optional
# Default: true
################################################################
# Ping configuration
################################################################
# Enable ping
ping:
# Name of the related entry point
#
# Optional
# Default: "traefik"
#
entryPoint: traefik
################################################################
# Docker configuration backend
################################################################
providers:
file:
filename: ./file-mirror.yml
# Enable Docker configuration backend
# docker:
# Docker server endpoint. Can be a tcp or a unix socket endpoint.
#
# Required
# Default: "unix:///var/run/docker.sock"
#
# endpoint: tcp://10.10.10.10:2375
# Default host rule.
#
# Optional
# Default: "Host(`{{ normalize .Name }}`)"
#
# defaultRule: Host(`{{ normalize .Name }}.docker.localhost`)
# Expose containers by default in traefik
#
# Optional
# Default: true
#
# exposedByDefault: false
路由及镜像配置文件
注:有10%的流量会被复制到appv2
http:
routers:
myrouter-1:
rule: "PathPrefix(`/server_1`)"
service: "mirrored-svc"
entryPoints:
- web
services:
mirrored-svc:
mirroring:
service: appv1
maxBodySize: 1024
mirrors:
- name: appv2
percent: 10
appv1:
loadBalancer:
servers:
- url: http://127.0.0.1:8888
appv2:
loadBalancer:
servers:
- url: http://127.0.0.1:18888
主服务
package main
import (
"fmt"
"net/http"
"sync/atomic"
)
var HTTP_PRE = "/server_1"
var count int32 = 0
func HelloHandle(w http.ResponseWriter, r *http.Request) {
i := atomic.AddInt32(&count, 1)
msg:= " hello! this is go http server 1. port = 8888" + fmt.Sprintf(" count = %d",i)
fmt.Println(msg)
_, _ = fmt.Fprint(w, msg)
}
func main() {
http.HandleFunc(HTTP_PRE + "/hello", HelloHandle)
if e := http.ListenAndServe(":8888", nil); e!= nil{
panic(e.Error())
}
}
镜像服务
package main
import (
"fmt"
"net/http"
)
var HTTP_PRE = "/server_1"
func HelloHandle(w http.ResponseWriter, r *http.Request) {
msg:= " hello! this is go http server 1 mirror. port = 18888"
fmt.Println(msg)
_, _ = fmt.Fprint(w, msg)
}
func main() {
http.HandleFunc(HTTP_PRE + "/hello", HelloHandle)
if e := http.ListenAndServe(":18888", nil); e!= nil{
panic(e.Error())
}
}
启动traefik服务
traefik.exe --configFile=traefik-sample.yml
多次访问 http://127.0.0.1/server_1/hello 会看到效果
traefik中的Mirroring对象负责流量复制,它继承go原生的net.http.server.Handler接口,在实现的ServeHTTP方法中首先将请求的body对象读取出来存到byte数组中,通过byte数组创建流覆盖源req的body(源body读取之后不这样操作会报eof错误),正常的请求收到响应之后,再新起协程通过已读byte数组及ctx 创建req对象,返回时通过使用实现的ResponseWriter对象,在Write时执行空操作来丢弃流量复制这块的响应包
参考链接:
https://doc.traefik.io/traefik/routing/services/#mirroring-service