英文:
Traefik v2 reverse proxy without Docker
问题
我有一个非常简单的 Golang 微服务(没有 Docker,只是一个简单的二进制文件),它在 GET 请求上返回简单的消息。
curl -XGET 'http://localhost:36001/api/operability/list'
> {"message": "ping 123"}
现在我想通过 Traefik-v2 进行反向代理,所以我创建了配置文件 "traefik.toml":
[global]
checkNewVersion = false
sendAnonymousUsage = false
[entryPoints]
[entryPoints.web]
address = ":8090"
[entryPoints.traefik]
address = ":8091"
[log]
level = "DEBUG"
filePath = "logs/traefik.log"
[accessLog]
filePath = "logs/access.log"
[api]
insecure = true
dashboard = true
[providers]
[providers.file]
filename = "traefik.toml"
# dynamic conf
[http]
[http.routers]
[http.routers.my-router]
rule = "Path(`/proxy`)"
service = "my-service"
entryPoints = ["web"]
[http.services]
[http.services.my-service.loadBalancer]
[[http.services.my-service.loadBalancer.servers]]
url = "http://localhost:36001"
启动 Traefik(我使用的是二进制发行版):
traefik --configFile=traefik.toml
现在端口 8091 上的仪表板正常工作,但我在反向代理请求方面遇到了困难。根据我的配置文件,我认为请求应该是这样的:
curl -XGET 'http://localhost:8090/proxy/api/operability/list'
但是我得到的只是:
> 404 页面未找到
问题是:配置文件中是否有任何错误,还是只是请求的拼写错误?
编辑:
我的配置文件基于以下问题的答案:
- https://stackoverflow.com/questions/60227270/simple-reverse-proxy-example-with-traefik
- https://stackoverflow.com/questions/58496270/traefik-v2-as-a-reverse-proxy-without-docker
编辑 #2:
Traefik 版本信息:
traefik version
Version: 2.4.9
Codename: livarot
Go version: go1.16.5
Built: 2021-06-21T16:17:58Z
OS/Arch: windows/amd64
英文:
I have a dead simple Golang microservice (no Docker, just simple binary file) which returns simple message on GET-request.
curl -XGET 'http://localhost:36001/api/operability/list'
> {"message": "ping 123"}
Now I want to do reverse proxy via Traefik-v2, so I've made configuration file "traefik.toml":
[global]
checkNewVersion = false
sendAnonymousUsage = false
[entryPoints]
[entryPoints.web]
address = ":8090"
[entryPoints.traefik]
address = ":8091"
[log]
level = "DEBUG"
filePath = "logs/traefik.log"
[accessLog]
filePath = "logs/access.log"
[api]
insecure = true
dashboard = true
[providers]
[providers.file]
filename = "traefik.toml"
# dynamic conf
[http]
[http.routers]
[http.routers.my-router]
rule = "Path(`/proxy`)"
service = "my-service"
entryPoints = ["web"]
[http.services]
[http.services.my-service.loadBalancer]
[[http.services.my-service.loadBalancer.servers]]
url = "http://localhost:36001"
Starting Traefik (I'm using binary distribution):
traefik --configFile=traefik.toml
Now dashboard on port 8091 works like a charm, but I struggle with reverse proxy request. I suppose it should look like this (based on my configuration file):
curl -XGET 'http://localhost:8090/proxy/api/operability/list'
But all I get it's just:
> 404 page not found
The question is: is there any mistake in configuration file or is it just a request typo?
edit:
My configuration file is based on answers in this questions:
- https://stackoverflow.com/questions/60227270/simple-reverse-proxy-example-with-traefik
- https://stackoverflow.com/questions/58496270/traefik-v2-as-a-reverse-proxy-without-docker
edit #2:
Traefik version info:
traefik version
Version: 2.4.9
Codename: livarot
Go version: go1.16.5
Built: 2021-06-21T16:17:58Z
OS/Arch: windows/amd64
答案1
得分: 3
我已经找到答案。
-
如果我决定使用Traefik将_/proxy_重定向到_/api/*_,那么我并不聪明。官方文档(https://doc.traefik.io/traefik/routing/routers/)中说道(我引用一下):
如果你的服务只监听特定路径,请使用Path。例如,Path: /products将匹配/products,但不匹配/products/shoes。
如果你的服务监听特定基础路径,并且还处理子路径的请求,请使用Prefix匹配器。例如,PathPrefix: /products将匹配/products,也将匹配/products/shoes和/products/shirts。由于路径被原样转发,你的服务应该监听/products。
-
我没有使用任何中间件来替换路径的子字符串。
现在给出一个示例。
首先,是main.go文件中的微服务代码:
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, `{"message": "ping 123"}`)
}
func main() {
http.HandleFunc("/operability/list", handler)
log.Fatal(http.ListenAndServe(":36001", nil))
}
接下来是Traefik v2的配置文件config.toml:
[global]
checkNewVersion = false
sendAnonymousUsage = false
[entryPoints]
[entryPoints.web]
address = ":36000"
[entryPoints.traefik]
address = ":8091"
[log]
level = "DEBUG"
filePath = "logs/traefik.log"
[accessLog]
filePath = "logs/access.log"
[api]
insecure = true
dashboard = true
[providers]
[providers.file]
debugLogGeneratedTemplate = true
# Point this same file for dynamic configuration
filename = "config.toml"
watch = true
[http]
[http.middlewares]
[http.middlewares.test-replacepathregex.replacePathRegex]
# We need middleware to replace all "/proxy/" with "/api/"
regex = "(?:^|\W)proxy(?:$|\W)"
replacement = "/api/"
[http.routers]
[http.routers.my-router]
# We need to handle all request with pathes defined as "/proxy/*"
rule = "PathPrefix(`/proxy/`)"
service = "my-service"
entryPoints = ["web"]
# Use of defined middleware for path replacement
middlewares = ["test-replacepathregex"]
[http.services]
[http.services.my-service.loadBalancer]
[[http.services.my-service.loadBalancer.servers]]
url = "http://localhost:36001/"
启动微服务:
go run main.go
启动Traefik:
traefik --configFile config.toml
现在检查微服务是否正常工作:
curl -XGET 'http://localhost:36001/api/operability/list'
{"message": "ping 123"}
然后检查Traefik v2是否正常工作:
curl -XGET 'http://localhost:36000/proxy/operability/list'
{"message": "ping 123"}
英文:
I've managed to find the answer.
- I'm not that smart if I've decided that Traefik would take /proxy and simply redicrect all request to /api/*. The official docs (https://doc.traefik.io/traefik/routing/routers/) says that (I'm quoting):
>> Use Path if your service listens on the exact path only. For instance, Path: /products would match /products but not /products/shoes.
>> Use a Prefix matcher if your service listens on a particular base path but also serves requests on sub-paths. For instance, PathPrefix: /products would match /products but also /products/shoes and /products/shirts. Since the path is forwarded as-is, your service is expected to listen on /products.
- I did not use any middleware for replacing substring of path
Now answer as example.
First at all: code for microservice in main.go file
package main
import (
"fmt"
"log"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "{\"message\": \"ping 123\"}")
}
func main() {
http.HandleFunc("/operability/list", handler)
log.Fatal(http.ListenAndServe(":36001", nil))
}
Now, configuration file for Traefik v2 in config.tom file:
[global]
checkNewVersion = false
sendAnonymousUsage = false
[entryPoints]
[entryPoints.web]
address = ":36000"
[entryPoints.traefik]
address = ":8091"
[log]
level = "DEBUG"
filePath = "logs/traefik.log"
[accessLog]
filePath = "logs/access.log"
[api]
insecure = true
dashboard = true
[providers]
[providers.file]
debugLogGeneratedTemplate = true
# Point this same file for dynamic configuration
filename = "config.toml"
watch = true
[http]
[http.middlewares]
[http.middlewares.test-replacepathregex.replacePathRegex]
# We need middleware to replace all "/proxy/" with "/api/"
regex = "(?:^|\\W)proxy(?:$|\\W)"
replacement = "/api/"
[http.routers]
[http.routers.my-router]
# We need to handle all request with pathes defined as "/proxy/*"
rule = "PathPrefix(`/proxy/`)"
service = "my-service"
entryPoints = ["web"]
# Use of defined middleware for path replacement
middlewares = ["test-replacepathregex"]
[http.services]
[http.services.my-service.loadBalancer]
[[http.services.my-service.loadBalancer.servers]]
url = "http://localhost:36001/"
Start microservice:
go run main.go
Start traefik:
traefik --configFile config.toml
Now check if microservice works correctly:
> curl -XGET 'http://localhost:36001/api/operability/list'
>> {"message": "ping 123"}
And check if Traefik v2 does job well too:
> curl -XGET 'http://localhost:36000/proxy/operability/list'
>> {"message": "ping 123"}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论