1. 程式人生 > >kong個人分享(api網關)

kong個人分享(api網關)

數據庫 structure 核心 package ssa 我們 port entos defaults

# kong簡介

## 背景

我們在提供api或微服務時,通常借助openresty nginx進行流量轉發或者添加一些規則或功能,但是隨著服務數量和引用增多,復雜的網絡環境,
使維護變得困難,不容易擴展,一些功能也會在多個服務中重復,我們期望有一個工具來集中管理。

![](images/kong_arch.png)

## 簡介

Kong 是在客戶端和(微)服務間轉發API通信的API網關和API服務管理層,通過插件擴展功能。我們可以
可以通過增加更多 Kong Server 機器對 Kong 服務進行水平擴展,通過前置的負載均衡器向這些機器分發請求。

* 官網:https://getkong.org/
* github:https://github.com/Mashape/kong
* kong-dashboard(開源UI):https://www.npmjs.com/package/kong-dashboard

## 特點

* Kong核心基於OpenResty構建,實現了請求/響應的Lua處理化
* Kong通過Restful API提供了API/API消費者/插件/upstream/sni/證書的管理;
* 數據中心用於存儲Kong集群節點信息、API、消費者、插件等信息,目前提供了PostgreSQL和Cassandra支持,如果需要高可用建議使用Cassandra;
* 緩存機制(為了避免每次查詢數據庫,Kong 在第一次請求之行時,嘗試在本地的內存裏做盡可能多的數據緩存。)、kong集群使kong具備高性能高可用.

## 結構
* admin: restful api<-->kong server<-(cache)-->db
* client:port--->[kong server<--(cache)-->db]-->api

## 安裝

* kong:0.11

```bash
$ sudo yum install epel-release
$ sudo yum install kong-community-edition-0.11.0.*.noarch.rpm --nogpgcheck
```
* PostgreSQL 9.4+ and Cassandra 3.x.x

```bash
yum install postgresql96-server postgresql96-contrib
```
## 配置

* 配置文件

```bash
/etc/kong/kong.conf
/usr/local/kong/nginx.conf
/usr/local/kong/nginx-kong.conf
```
* 模板:

```bash
kong_defaults.lua
nginx.lua
nginx_kong.lua
```

## 表結構

## kong常用命令

* kong

```bash
kong --v
kong check /etc/kong/kong.conf
kong health -p /usr/local/kong
kong version
```
* 初始化數據庫,插件更新

```bash
kong migrations up -c /etc/kong/kong.conf
kong migrations list -c /etc/kong/kong.conf
kong migrations reset -c /etc/kong/kong.conf
```
* 配置

```bash
kong start -c /etc/kong/kong.conf -p /usr/local/kong --nginx-conf custom_nginx.template --run-migrations true
kong start -c /etc/kong/kong.conf --nginx-conf custom_nginx.template
kong quit -p /usr/local/kong
kong stop -p /usr/local/kong
kong reload -c /etc/kong/kong.conf -p /usr/local/kong --nginx-conf custom_nginx.template
```


## Kong Admin API
* method:
[get\patch\put\delete]

* 管理項:[apis\upstreams\plugins\consumers\certificates\snis]

* 格式

```bash
get:/apis/{name or id}
get:/apis/
patch:/apis/{name or id}
put:/apis/
delete:/apis/{name or id}
```

* config

``` bash
curl http://localhost:8001/ |jq .
curl http://localhost:8001/status |jq .
```

* /apis/

``` bash
curl -H "Content-type: application/json" -X POST -d ‘{"name":"demo","hosts":"demo.com","upstream_url":"http://www.baidu.com"}‘ "http://localhost:8001/apis/" | jq .
修改hosts-->reload
curl -H "Content-type: application/json" -X POST -d ‘{"name":"demo","hosts":"demo.com","upstream_url":"http://structuretest.com","preserve_host":"false"}‘ "http://localhost:8001/apis/" | jq .

curl -H "Content-type: application/json" -X POST -d ‘{"name":"demo","hosts":"demo.com","upstream_url":"http://demo.upstream"}‘ "http://localhost:8001/apis/" | jq .
curl -H "Content-type: application/json" -X PATCH -d ‘{"strip_uri":"true","preserve_host":"true", "https_only":"false","http_if_terminated":"true"}‘ "http://localhost:8001/apis/demo" |jq .
curl -H "Content-type: application/json" -X POST -d ‘{"name":"demo","hosts":"demo.com","upstream_url":"http://demo.upstream"}‘ "http://localhost:8001/apis/" | jq .
curl -X GET "http://localhost:8001/apis/demo" |jq .
curl -X GET "http://localhost:8001/apis/" |jq .
curl -X DELETE "http://localhost:8001/apis/demo" |jq .
```

* /upstreams/

``` bash
curl -H "Content-type: application/json" -X POST -d ‘{"name":"demo.upstream","slots":10}‘ "http://localhost:8001/upstreams/" | jq .
curl -X GET "http://localhost:8001/upstreams/demo.upstream" |jq .
curl -X GET "http://localhost:8001/upstreams" |jq .
curl -X DELETE "http://localhost:8001/upstreams/demo.upstream" |jq .
```

* /upstreams/{name or id}/targets

``` bash
curl -H "Content-type: application/json" -X POST -d ‘{"target":"192.168.226.129:8090","weight":1}‘ "http://localhost:8001/upstreams/demo.upstream/targets" | jq .
curl -X GET "http://localhost:8001/upstreams/test.upstream/targets" |jq .
curl -X GET "http://localhost:8001/upstreams" |jq .

curl -X DELETE "http://localhost:8001/upstreams/test.upstream/targets/target"
```

* /plugins/


``` bash
--修改刪除只能通過id;
curl -H "Content-type: application/json" -X POST -d ‘{"name":"key-auth"}‘ "http://localhost:8001/apis/demo/plugins/" |jq .
curl -H "Content-type: application/json" -X PATCH -d ‘{"enabled":"true","config.key_names":"apikey"}‘ "http://localhost:8001/apis/demo/plugins/9a14eea2-731b-48f7-8cb4-949ea9c0f25a" |jq .
curl -X GET "http://localhost:8001/plugins/" |jq .
curl -X GET "http://localhost:8001/apis/demo/plugins/" |jq .
curl -X DELETE "http://localhost:8001/apis/demo/plugins/9a14eea2-731b-48f7-8cb4-949ea9c0f25a" |jq .
```

* /consumers/

``` bash
curl -H "Content-type: application/json" -X POST -d ‘{"username":"demo-user"}‘ "http://localhost:8001/consumers/" |jq .
curl -X DELETE "http://localhost:8001/consumers/demo-user" |jq .
curl -X GET "http://localhost:8001/consumers/demo-user" |jq .
添加key:
curl -H "Content-type: application/json" -X POST -d ‘{"key":"api_key"}‘ "http://localhost:8001/consumers/demo-user/key-auth/" |jq .
```

* /certificates/

``` bash
curl -H "Content-type: application/json" -X POST -d ‘{"cert":"","key":"","snis":""}‘ "http://localhost:8001/apis/demo/certificates/" |jq .
```

* /snis/

``` bash
curl -H "Content-type: application/json" -X POST -d ‘{"name":"","ssl_certificate_id":""}‘ "http://localhost:8001/apis/demo/snis/" |jq .
```

## proxy routing 規則

* 配置多項

``` bash
備註:下面是接口響應格式
{
"name": "my-api",
"upstream_url": "http://my-api.com",
"hosts": ["example.com", "service.com"],
"uris": ["/foo", "/bar"],
"methods": ["GET"]
}
```

* 遵循最長匹配優先評估,

``` bash
"uris": ["/version/\d+/status/\d+"]
"uris": ["/version"]
"uris": ["/"]

--請求
GET /version/3/status/3 匹配第一個
GET /version 匹配第二個
GET /version/123 匹配第二個
GET /vs 匹配第三個
```


## Load Balancing reference

* DNS based loadbalancing:dns_resolver配置dns ip,解析多個ip後,自動使用基於DNS負載均衡(加權負載均衡器,將做一個簡單的循環),當dns_stale_ttl 超時後請求dns;

* Ring-balancer:upstream(slots\orderlist)\ target(weight)

## 集群

* 0.11版本:當一個節點發生更新到數據庫後,其他節點需要間隔db_update_frequency後,更新緩存失效字段。在使用Cassandra數據庫db_update_propagation(數據節點傳播延時)必須配置。
為防止db_update_frequency後錯過一個失效事件,db_cache_ttl全量更新cache

``` bash
db_update_frequency = 5
db_update_propagation = 0
db_cache_ttl = 3600
```

* 0.10版本:通過 Kong 集群,每個節點能夠知道其它節點的存在。並且當一個Kong 節點有對數據更新,該節點有責任通知這個變化給集群裏的其他節點,
通知其其他節點把本地內存中的緩存無效,重新從數據庫中獲取更新後的數據。

``` bash
cluster_listen 通信
cluster_listen_rpc 代理通信
cluster_advertise
cluster_encrypt_key base64編碼16字節加密集群通信
cluster_keyring_file
cluster_ttl_on_failure //失敗節點超時後停止被鏈接;
cluster_profile //local, lan, wan.

--數據庫node表來存儲節點信息:
node
VM_3_3_centos_0.0.0.0:7946_58b54877bc4a47d884b9986e71f49d8b | 10.100.3.3:7946 | 2017-08-07 04:29:05
VM_3_2_centos_0.0.0.0:7946_e4147c192bcc4401acf698ca6374d59d | 10.100.3.2:7946 | 2017-06-12 10:19:24
```

## 常用插件

* 8個常用插件

## 編寫插件

* 文件結構

``` bash

基本
simple-plugin
├── handler.lua 一個接口來實現。每個函數是由kong一個請求的生命周期所需的時刻。(對應lua模塊的生命周期)
└── schema.lua 插件引入參數類型、規則、校驗

涉及數據庫
complete-plugin
├── api.lua 與kong restful對接
├── daos.lua 數據庫操作
├── handler.lua //
├── migrations
│ ├── cassandra.lua
│ └── postgres.lua //kong migrations操作數據初始化
└── schema.lua

```

* 編寫rockspec文件:

```bash
build = {
type = "builtin",
modules = {
["kong.plugins.my-plugin-addtag.handler"] = "kong/plugins/my-plugin-addtag/handler.lua",
["kong.plugins.my-plugin-addtag.schema"] = "kong/plugins/my-plugin-addtag/schema.lua"
}
}
```

```bash
luarocks make --pack-binary-rock my-plugin-addtag-0.1.0-0.rockspec
```

* 修改kong.conf custom_plugins 掛載,重啟;

## 測試環境使用情況

```bash
http://172.16.17.9:5664/#/apis
```

kong個人分享(api網關)