和APISIX类似,Kong也是一个Api GateWay。
运行在调用Api之前,以插件的扩展方式为Api提供管理, 如 鉴权、限流、监控、健康检查等. Kong是基于Lua语言、Nginx以及OpenResty开发的,拥有动态路由、负载均衡、高可用、高性能、熔断(基于健康检查)等功能。
和APIXIS不同,不用etcd做存储,而使用PostgreSQL,最早用的是Apache Cassandra
基础使用
安装过程忽略,可使用docker一键搭建
假设我有一个服务A,对外提供多个接口。现在想要使用Kong对其进行管理
服务A所在的机器,和运行kong的机器不一定是一台.
Kong就是个网关,统一入口。
服务A如下,
package main
import (
"fmt"
"net/http"
"time"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/hello" {
currentTime := time.Now().Format("2006-01-02 15:04:05")
response := fmt.Sprintf("你好,当前时间是%s", currentTime)
fmt.Fprint(w, response)
} else {
http.NotFound(w, r)
}
}
func main() {
http.HandleFunc("/", helloHandler)
fmt.Println("Server is running on port 58888")
err := http.ListenAndServe(":58888", nil)
if err != nil {
fmt.Println("Error starting server:", err)
}
}
即 curl 服务所在机器的公网IP:58888/hello
会返回当前的时间
在kong的控制台, http://Kong所在机器的公网IP:8002 创建一个Gateway Service,
其中,Host写要代理的那个服务的地址(即A所在机器的公网IP),端口写相应的端口
如果是域名,则端口写默认的80
然后新建一条Routes
然后, 就可以通过 curl http://Kong服务的公网IP:8000/上图写的Paths/hello
来访问了
得到的结果还是一样的,但会先通过kong,就能做很多事情了…比如限流,鉴权,日志啥的…
记录接口的请求和响应内容
Kong也提供了很多直接可用的插件,下面以HTTP Log
插件为例, 使用该插件,可以记录接口的请求和响应内容
在Plugins处点击New Plugin,
搜索HTTP
再写一个服务(该服务监听20017端口),提供一个接口,用来接收:58888 这个服务全部的请求和响应内容
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
)
func getRequestHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
return
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Error reading request body: %v", err)
return
}
defer r.Body.Close()
log.Printf("Received request: %s", string(body))
// 在这里可以对请求体进行处理
// ...
// 如果需要响应内容,可以在这里写入响应体
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, "Request received successfully")
}
func main() {
http.HandleFunc("/getrequest", getRequestHandler)
log.Println("Starting server on port 20017...")
err := http.ListenAndServe(":20017", nil)
if err != nil {
log.Fatalf("Failed to start server: %v", err)
}
}
然后执行 curl http://kong所在机器的公网IP:port/xxxx/hello\?1121312
:20017服务能够收到请求如下:
{
"service": {
"retries": 5,
"created_at": 1716538997,
"updated_at": 1716551161,
"write_timeout": 60000,
"port": 58888,
"name": "xxxxxxx",
"protocol": "http",
"connect_timeout": 60000,
"read_timeout": 60000,
"host": "111.222.222.111",
"enabled": true,
"ws_id": "7aa29e13-25cb-4920-992e-fe5b64576c21",
"tags": ["xxxxx-test"],
"id": "55bd77b4-b182-4e6b-87f1-a46608d27435"
},
"client_ip": "1.2.3.4",
"route": {
"created_at": 1716551271,
"updated_at": 1716551271,
"regex_priority": 0,
"service": {
"id": "55bd77b4-b182-4e6b-87f1-a46608d27435"
},
"paths": ["/xxxxx"],
"name": "xxxxxxx123",
"path_handling": "v0",
"id": "8481a0d0-05c2-4631-89eb-19d9aad10642",
"ws_id": "7aa29e13-25cb-4920-992e-fe5b64576c21",
"protocols": ["http"],
"strip_path": true,
"preserve_host": false,
"request_buffering": true,
"response_buffering": true,
"tags": [],
"https_redirect_status_code": 426
},
"started_at": 1716555189008,
"source": "upstream",
"tries": [{
"balancer_start": 1716555189008,
"balancer_start_ns": 1.7165551890087e+18,
"ip": "110.120.119.114",
"balancer_latency": 0,
"port": 58888,
"balancer_latency_ns": 15616
}],
"response": {
"size": 306,
"status": 200,
"headers": {
"x-kong-request-id": "d32e6a5e11bec9085663513c9430565b",
"date": "Fri, 24 May 2024 12:53:09 GMT",
"via": "kong/3.6.1",
"x-kong-proxy-latency": "0",
"content-length": "41",
"connection": "close",
"x-kong-upstream-latency": "98",
"content-type": "text/plain; charset=utf-8"
}
},
"upstream_status": "200",
"upstream_uri": "/hello",
"latencies": {
"kong": 0,
"request": 98,
"proxy": 98
},
"request": {
"size": 94,
"id": "d32e6a5e11bec9085663513c9430565b",
"headers": {
"user-agent": "curl/8.4.0",
"host": "xxx.xxx.xxx.xxx:8000",
"accept": "*/*"
},
"url": "http://xxxxxxxx:8000/xxxxx/hello",
"querystring": {},
"uri": "/xxxxx/hello",
"method": "GET"
}
}
但发现此时,request内容是比较详细的,但缺少response部分
参考 https://tech.aufomm.com/how-to-log-request-and-response-body-with-kong/
搜索Kong Functions (Pre-Plugins)
插件,
并设置Access为: kong.log.set_serialize_value("request.body", kong.request.get_raw_body())
Body Filter为: kong.log.set_serialize_value("response.body", kong.response.get_raw_body())
再次执行 curl http://Kong所在机器公网IP:8000/xxxxx/hello\?1121312
此时就能获取到完整的response内容
本文由mdnice多平台发布