Github GitHub - JasonkayZK/Go_Learn at easegress-demo
source link: https://github.com/JasonkayZK/Go_Learn/tree/easegress-demo
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Easegress Demo
A demo to show how to use easegress(An all-rounder traffic orchestration system)
一个展示流量编排系统easegress基本使用的例子;
Easegress是一个开源的流量编排系统(An all-rounder traffic orchestration system),居官方介绍这个系统通过Raft共识算法(实际上就是etcd)提供了分布式情况下的高可用、可以实现流量API调度、支持高并发高性能场景;
当然在我体验之后发现其实这个系统最特别的地方(与传统Nginx相比)在于Easegress是通过插件的方式直接进行热替换进行的(如果你使用过K8S,对于这种方式应该不会陌生);
本文介绍了Easegress的基本用法;
安装Easegress
Easegress的安装可以说是相当简单了;
其实就是两个二进制文件:
- easegress-server
- egctl
可以直接通过下载仓库的Release安装:
下载后解压,然后将二进制直接放入$PATH$
环境变量即可;
当然,也可以通过编译源码安装,这里不作介绍了;
启动服务器
启动服务器非常简单,我们可以直接使用默认参数启动:
[root@localhost easegress]# easegress-server WARNING: Package "github.com/golang/protobuf/protoc-gen-go/generator" is deprecated. A future release of golang/protobuf will delete this package, which has long been excluded from the compatibility promise. 2021-06-13T09:47:09.205+08:00 INFO server/main.go:61 Easegress release: v1.0.0, repo: megaease/easegress, commit: 3dd74e5b01d0852ed5dffe03de9b4d48a64667e7 2021-06-13T09:47:09.205+08:00 INFO storage/storage.go:250 /root/workspace/easegress/running_objects.yaml not exist 2021-06-13T09:47:09.205+08:00 INFO cluster/cluster.go:186 starting etcd cluster 2021-06-13T09:47:09.205+08:00 INFO cluster/cluster.go:382 client connect with endpoints: [http://localhost:2380] 2021-06-13T09:47:09.205+08:00 INFO cluster/config.go:126 etcd config: init-cluster:eg-default-name=http://localhost:2380 cluster-state:new force-new-cluster:false 2021-06-13T09:47:09.206+08:00 INFO cluster/cluster.go:396 client is ready 2021-06-13T09:47:09.733+08:00 INFO cluster/cluster.go:607 server is ready 2021-06-13T09:47:09.734+08:00 INFO cluster/cluster.go:468 lease is ready 2021-06-13T09:47:09.734+08:00 INFO cluster/cluster.go:204 cluster is ready 2021-06-13T09:47:09.763+08:00 INFO storage/storage.go:250 /root/workspace/easegress/running_objects.yaml not exist 2021-06-13T09:47:09.764+08:00 INFO supervisor/supervisor.go:197 create system controller StatusSyncController 2021-06-13T09:47:09.764+08:00 INFO cluster/cluster.go:513 session is ready 2021-06-13T09:47:09.765+08:00 INFO api/api.go:113 api server running in localhost:2381 2021-06-13T09:47:14.738+08:00 INFO cluster/member.go:233 self ID changed from 0 to 689e371e88f78b6a 2021-06-13T09:47:14.739+08:00 INFO cluster/member.go:154 store clusterMembers: eg-default-name(689e371e88f78b6a)=http://localhost:2380 2021-06-13T09:47:14.739+08:00 INFO cluster/member.go:155 store knownMembers : eg-default-name(689e371e88f78b6a)=http://localhost:2380
此时会监听默认的2379、2380、2381
三个端口;
同时会在当前启动目录创建一些文件:
- data目录;
- log目录;
- member目录;
- easegress.pid文件:记录当前easegress-server的pid;
启动成功后尝试查看成员列表:
[root@localhost easegress]# egctl member list - options: name: eg-default-name labels: {} cluster-name: eg-cluster-default-name cluster-role: writer cluster-request-timeout: 10s cluster-listen-client-urls: - http://localhost:2379 cluster-listen-peer-urls: - http://localhost:2380 cluster-advertise-client-urls: - http://localhost:2379 cluster-initial-advertise-peer-urls: - http://localhost:2380 cluster-join-urls: [] api-addr: localhost:2381 debug: false home-dir: ./ data-dir: data wal-dir: "" log-dir: log member-dir: member cpu-profile-file: "" memory-profile-file: "" lastHeartbeatTime: "2021-06-13T12:55:21+08:00" etcd: id: 689e371e88f78b6a startTime: "2021-06-13T09:47:09+08:00" state: Leader
这是我们所启动的一个单节点集群的信息;
系统测试
创建HTTPServer
首先,我们创建一个HTTPServer
来控制服务器的流量:
下面是官方提供的一个例子:
$ echo ' kind: HTTPServer name: server-demo port: 10080 keepAlive: true https: false rules: - paths: - pathPrefix: /pipeline backend: pipeline-demo' | egctl object create
上面的配置会创建一个名称为server-demo
的HTTPServer
类型的组件,该组件监听10080
端口的/pipeline
路由,并转发至pipeline-demo
组件;
创建完成后,server端产生日志:
2021-06-13T09:48:30.195+08:00 INFO supervisor/supervisor.go:273 create server-demo
注意到:我们还没有创建名称叫做
pipeline-demo
的组件,因此,此时访问127.0.0.1:10080/pipeline
会报503错误;
[root@localhost easegress]# curl -v 127.0.0.1:10080/pipeline * About to connect() to 127.0.0.1 port 10080 (#0) * Trying 127.0.0.1... * Connected to 127.0.0.1 (127.0.0.1) port 10080 (#0) > GET /pipeline HTTP/1.1 > User-Agent: curl/7.29.0 > Host: 127.0.0.1:10080 > Accept: */* > < HTTP/1.1 503 Service Unavailable < Date: Sun, 13 Jun 2021 05:08:14 GMT < Content-Length: 0 < * Connection #0 to host 127.0.0.1 left intact
下面创建HTTPPipeline;
创建HTTPPipeline
HTTPPipeline是Easegress的核心部分,用于过滤、校验和转发HTTP请求!
下面我们来创建一个HTTPPipeline;
下面的例子同样由官方提供:
$ echo ' name: pipeline-demo kind: HTTPPipeline flow: - filter: proxy filters: - name: proxy kind: Proxy mainPool: servers: - url: http://127.0.0.1:9095 - url: http://127.0.0.1:9096 - url: http://127.0.0.1:9097 loadBalance: policy: roundRobin' | egctl object create
server端日志:
2021-06-13T13:14:54.667+08:00 INFO supervisor/supervisor.go:273 create pipeline-demo
这个HTTPPipeline将使用roundRobin
算法为后端的三个服务提供负载均衡:
这时我们还是不能进行测试的,因为我们还没有后端服务;
所幸官方已经提供了这么一个后端服务:
下面我们来启动后端服务;
启动后端服务
为了让我们的测试更加明显,我对官方提供的服务做了一些修改;
修改后的后端服务的代码如下:
mirror.go
package main import ( "flag" "fmt" "io" "io/ioutil" "net/http" "time" ) func main() { port := flag.Int("p", 9095, "server port, default: 9095") flag.Parse() helloHandler := func(w http.ResponseWriter, req *http.Request) { _, _ = io.WriteString(w, "hello") } mirrorHandler := func(w http.ResponseWriter, req *http.Request) { time.Sleep(10 * time.Millisecond) body, err := ioutil.ReadAll(req.Body) if err != nil { body = []byte(fmt.Sprintf("<read failed: %v>", err)) } url := req.URL.Path if req.URL.Query().Encode() != "" { url += "?" + req.URL.Query().Encode() } content := fmt.Sprintf(`Your Request server from port %d =============== Method: %s URL : %s Header: %v Body : %s\n `, *port, req.Method, url, req.Header, body) _, _ = io.WriteString(w, content) } http.HandleFunc("/", mirrorHandler) http.HandleFunc("/pipeline/activity/1", helloHandler) http.HandleFunc("/pipeline/activity/2", helloHandler) fmt.Printf("Server started at port: %d\n", *port) _ = http.ListenAndServe(fmt.Sprintf(":%d", *port), nil) }
可以看到,服务默认监听了9095
端口,但是我们可以通过
同时,各个路由的Handler:
/
:mirrorHandler;/pipeline/activity/1
:helloHandler;/pipeline/activity/2
:helloHandler;
下面启动服务:
[root@localhost easegress]# go run mirror.go & Server started at port: 9095 [root@localhost easegress]# go run mirror.go -p 9096 & Server started at port: 9096 [root@localhost easegress]# go run mirror.go -p 9097 & Server started at port: 9097 # 查看后台服务 [root@localhost easegress]# jobs [1] Running go run mirror.go & [2]- Running go run mirror.go -p 9096 & [3]+ Running go run mirror.go -p 9097 &
服务已经成功启动,并监听9095~9097
端口;
服务测试
注意到,在之前的配置中,我们创建的HTTPServer
监听的是10080
端口的/pipeline
路由,并将流量转发至HTTPPipeline
;
而HTTPPipeline
会负载均衡至http://127.0.0.1:9095
~http://127.0.0.1:9097
三个服务;
所以我们通过访问http://127.0.0.1:10080/pipeline
进行测试!
测试如下:
[root@localhost easegress]# curl http://127.0.0.1:10080/pipeline -d 'Hello, Easegress' Your Request server from port 9095 =============== Method: POST URL : /pipeline Header: map[Accept:[*/*] Accept-Encoding:[gzip] Content-Type:[application/x-www-form-urlencoded] User-Agent:[curl/7.29.0]] Body : Hello, Easegress [root@localhost easegress]# curl http://127.0.0.1:10080/pipeline -d 'Hello, Easegress' Your Request server from port 9096 =============== Method: POST URL : /pipeline Header: map[Accept:[*/*] Accept-Encoding:[gzip] Content-Type:[application/x-www-form-urlencoded] User-Agent:[curl/7.29.0]] Body : Hello, Easegress [root@localhost easegress]# curl http://127.0.0.1:10080/pipeline -d 'Hello, Easegress' Your Request server from port 9097 =============== Method: POST URL : /pipeline Header: map[Accept:[*/*] Accept-Encoding:[gzip] Content-Type:[application/x-www-form-urlencoded] User-Agent:[curl/7.29.0]] Body : Hello, Easegress [root@localhost easegress]# curl http://127.0.0.1:10080/pipeline -d 'Hello, Easegress' Your Request server from port 9095 =============== Method: POST URL : /pipeline Header: map[Accept:[*/*] Accept-Encoding:[gzip] Content-Type:[application/x-www-form-urlencoded] User-Agent:[curl/7.29.0]] Body : Hello, Easegress
可以看到,服务的确是以roundRobin
算法来进行负载均衡的!
热替换Filter
上面我们定义了一个负载均衡的Filter,具体内容如下:
name: pipeline-demo kind: HTTPPipeline flow: - filter: proxy filters: - name: proxy kind: Proxy mainPool: servers: - url: http://127.0.0.1:9095 - url: http://127.0.0.1:9096 - url: http://127.0.0.1:9097 loadBalance: policy: roundRobin
下面,我们通过Easegress插件式的热替换,将现有的HTTPPipeline替换为其他类型的;
我们在原来的HTTPPipeline之上,增加参数校验和请求适配功能;
创建pipeline-demo.yaml
文件:
pipeline-demo.yaml
name: pipeline-demo kind: HTTPPipeline flow: - filter: validator jumpIf: { invalid: END } - filter: requestAdaptor - filter: proxy filters: - name: validator kind: Validator headers: Content-Type: values: - application/json - name: requestAdaptor kind: RequestAdaptor header: set: X-Adapt-Key: goodplan - name: proxy kind: Proxy mainPool: servers: - url: http://127.0.0.1:9095 - url: http://127.0.0.1:9096 - url: http://127.0.0.1:9097 loadBalance: policy: roundRobin
下面介绍一下上面的配置;
首先在flow
部分,定义了整个HTTPPipeline的过滤流(过滤链),同时如果在validator
部分出现了invalid
,则直接退出Filter;
flow
部分定义的各个步骤都在下面的filters
数组中定义;
在validator
中,我们定义了一个Validator
类型的Filter,用于校验header
中包括了Content-Type:"application/json"
;
在requestAdaptor
中,我们定义了RequestAdaptor
类型的Filter,用于在响应的Header
中添加X-Adapt-Key: "goodplan"
;
proxy
仍然是我们之前的定义;
文件编辑后,通过egctl object update -f
应用(类似于kubectl apply -f
):
egctl object update -f pipeline-demo.yaml
更新后server端日志:
2021-06-13T14:19:44.233+08:00 INFO supervisor/supervisor.go:276 update pipeline-demo
此时再进行测试:
[root@localhost easegress]# curl -v http://127.0.0.1:10080/pipeline -d 'Hello, Easegress' * About to connect() to 127.0.0.1 port 10080 (#0) * Trying 127.0.0.1... * Connected to 127.0.0.1 (127.0.0.1) port 10080 (#0) > POST /pipeline HTTP/1.1 > User-Agent: curl/7.29.0 > Host: 127.0.0.1:10080 > Accept: */* > Content-Length: 16 > Content-Type: application/x-www-form-urlencoded > * upload completely sent off: 16 out of 16 bytes < HTTP/1.1 400 Bad Request < Date: Sun, 13 Jun 2021 06:20:25 GMT < Content-Length: 0 < * Connection #0 to host 127.0.0.1 left intact
可以看到Server端返回400错误!
加上Header后再次测试:
[root@localhost easegress]# curl http://127.0.0.1:10080/pipeline -H 'Content-Type: application/json' -d '{"message": "Hello, Easegress"}' Your Request server from port 9095 =============== Method: POST URL : /pipeline Header: map[Accept:[*/*] Accept-Encoding:[gzip] Content-Type:[application/json] User-Agent:[curl/7.29.0] X-Adapt-Key:[goodplan]] Body : {"message": "Hello, Easegress"}
可以看到,请求正常返回;
同时,返回的响应中的Header部分加入了X-Adapt-Key:[goodplan]]
;
也可以通过egctl object list
查看相关组件:
[root@localhost easegress]# egctl object list - filters: - headers: Content-Type: values: - application/json kind: Validator name: validator - header: set: X-Adapt-Key: goodplan kind: RequestAdaptor name: requestAdaptor - kind: Proxy mainPool: loadBalance: policy: roundRobin servers: - url: http://127.0.0.1:9095 - url: http://127.0.0.1:9096 - url: http://127.0.0.1:9097 name: proxy flow: - filter: validator jumpIf: invalid: END - filter: requestAdaptor - filter: proxy kind: HTTPPipeline name: pipeline-demo - https: false keepAlive: true kind: HTTPServer name: server-demo port: 10080 rules: - paths: - backend: pipeline-demo pathPrefix: /pipeline
实验成功!
此处包括了更多类型的Filter说明:
总结
从上面的实验可以看到,Easegress使用起来还是很方便的;
仅仅通过配置文件即可对请求、路由等进行设置,体验和K8S基本上类似;
当然Easegress所提供的功能还有很多很多,有兴趣的可以查看官方文档:
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK