和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/xxxxx/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-...

搜索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内容


好文收藏
38 声望6 粉丝

好文收集