天天看点

KONG基础使用 注册API

kong是一个基于nginx的api gateway。提供了诸如身份认证,权限控制,流量控制,日志等一系列api相关的组件,可谓相当方便。

<a href="https://getkong.org/">kong项目首页</a>

<a href="https://getkong.org/docs/0.8.x/getting-started/quickstart/">kong入门</a>

<a href="https://github.com/mashape/kong/">kong的github地址</a>

<a href="https://getkong.org/docs/0.8.x/admin-api/">kong admin api一览</a>

<a href="https://getkong.org/plugins/">kong插件列表</a>

以linux redhat 6.2为例:

从此处下载对应二进制rpm包,按操作安装即可

<a href="https://getkong.org/install/redhat/">kong redhat release</a>

注意如果yum出现无法获取metalink的错误,

<code>sudo vi /etc/yum.repos.d/epel.repo</code>

注释掉所有mirrorlist,取消所有baseurl的注释即可。

kong是一个api gateway,顾名思义,就是api的出口。

内部系统的api可以随意编写,但如果要对外服务,就一定需要各种权限控制。

首先,我们写一个mock api,进行测试之用。

<code>import tornado.ioloop</code>

<code>import tornado.web</code>

<code></code>

<code>class mainhandler(tornado.web.requesthandler):</code>

<code>call_cnt = 0</code>

<code>def get(self):</code>

<code>mainhandler.call_cnt+= 1</code>

<code>self.write("get / %s"%mainhandler.call_cnt)</code>

<code>def post(self):</code>

<code>self.write("post / %s"%mainhandler.call_cnt)</code>

<code>class testhandler(tornado.web.requesthandler):</code>

<code>testhandler.call_cnt += 1</code>

<code>self.write("get /test %s"%testhandler.call_cnt)</code>

<code>self.write("post /test %s"%testhandler.call_cnt)</code>

<code>def make_app():</code>

<code>return tornado.web.application([</code>

<code>(r"/", mainhandler),</code>

<code>(r"/test", testhandler)</code>

<code>])</code>

<code>if __name__ == "__main__":</code>

<code>app = make_app()</code>

<code>app.listen(8812)</code>

<code>tornado.ioloop.ioloop.current().start()</code>

这是一个用tornado写的简易rest测试 api,用以下命令后台启动

<code>nohup python test_api.py 1&gt;/dev/null 2&gt;log &amp;;</code>

<code># 测试endpoint:/</code>

<code>curl -i -x get http://localhost:8812/</code>

<code>curl -i -x post http://localhost:8812/</code>

<code>curl -i -x delete http://localhost:8812/</code>

<code># 测试endpoint:/test</code>

<code>curl -i -x get http://localhost:8812/test</code>

<code>curl -i -x post http://localhost:8812/test</code>

<code>curl -i -x delete http://localhost:8812/test</code>

现在我们已经有一个正常工作的rest api了。是时候使用kong了。

kong的使用基本和nginx如出一辙。默认的工作目录是<code>/usr/local/kong</code>,默认的配置文件是<code>/etc/kong/kong.yml</code>。如果需要工作在1024以下的端口,则要求root权限。

kong的启动命令很简单,就是<code>kong start</code>

但是启动之前需要编辑配置文件。

需要关注的主要是几个点:

发送匿名统计报告,(默认打开,一定要关闭)

后端数据库的配置,(默认cassandra,建议postgres)

内存缓存大小配置,(默认128m,建议1g)

出口端口(默认http 8000,https 8443,建议直接改成80和443)

管理端口(默认8001,我改成8888比较吉利)

配置好之后,启动kong即可。

使用什么语言的http库都可以完成这个工作,这里直接使用linux自带的curl。

第一步,我们需要先注册我们的api

假设我们想把上面那个api挂载到/test路径下,

执行

<code># 查看当前已经注册的api</code>

<code>curl -x get http://localhost:8888/apis/</code>

<code># 注册一个新的api</code>

<code>curl -i -x post http://localhost:8888/apis/ -d "name=testapi" -d "request_path=/test" -d "upstream_url=http://localhost:8812/" -d "strip_request_path=true"</code>

这里注册url的几个参数意思是,这个api注册的名字叫testapi。它被挂载在网关的<code>/test</code>路径下,上游转发到<code>http://localhost:8812</code>去处理,转发的时候把前面的<code>/test</code>前缀给去掉。

<code>{"upstream_url":"http:\/\/localhost:8812\/","request_path":"\/test","id":"a302c28c-eb8a-4e53-bac2-9acb68695f3b","created_at":1468379310000,"preserve_host":false,"strip_request_path":true,"name":"testapi"}</code>

返回结果表明api创建的结果。一般会返回一个api的id。

这就表明api注册完成,我们可以测试一下:

<code>curl -i -x get http://localhost/test</code>

<code>curl -i -x post https://localhost/test/test --insecure</code>

如同我们预期的一样返回正确的结果,说明api已经成功注册。

当然,仅仅把api注册了开放出去,其实也就是把多个api集成到一个endpoint,实际意义并不大,下面我们来试一试高级一点的功能。

kong自带插件目前可以分为以下几类:

身份认证,安全,流量控制,分析监控,格式转换,日志。

有的api完全开放,不需要任何认证,有的api会涉及敏感数据,权限控制需要非常严格。有的api完全不在乎调用频次或者日志,有的则反过来。

值得高兴的是,kong的插件独立作用于每一个api,不同的api可以使用完全不同的插件。提供了相当灵活的配置策略。

现在我们首先给这个测试api加上基本的权限验证。

<code>curl -x post http://localhost:8888/apis/testapi/plugins -d "name=key-auth"</code>

<code># 这个时候再去调用这个api就会返回401 unauthorized</code>

朴素的api可能压根没有严格的用户概念,端口大开,随便哪个阿猫阿狗都能进来扫一扫看一看。这可不行。

kong有一个consumer的概念,consumer是全局共用的。

比如某个api启用了key-auth,那么没有身份的访问者就无法调用这个api了。

需要首先创建一个consumer,然后在key-auth插件中为这个consumer生成一个key。

然后就可以使用这个key来透过权限验证访问api了。

同理,如果另外一个api也开通了key-auth插件,那么这个consumer也是可以通过key-auth验证访问这个api的,如果要控制这种情况,就需要acl插件。

(认证与权限乃是两个不同的事物)

首先我们创建一个名为test_user的consumer

<code># 获取所有consumer列表</code>

<code>curl -x get http://localhost:8888/consumers/</code>

<code># 创建一个新的consumer</code>

<code>curl -x post http://localhost:8888/consumers/ -d "username=testuser"</code>

然后,我们在key-auth插件中为它创建一个key

<code>curl -x post http://localhost:8888/consumers/testuser/key-auth -d "key=testkey"</code>

这次加上apikey首部进行验证,成功调用

<code>curl -i -x get http://localhost/test --header "apikey: testkey"</code>

删除用户

<code>curl -i -x delete http://localhost:8888/consumers/testuser</code>

删除插件

<code># 查询api拥有的插件id</code>

<code>curl -i -x get http://localhost:8888/apis/testapi/plugins/</code>

<code># 根据插件id删除插件。</code>

<code>curl -i -x delete http://localhost:8888/apis/testapi/plugins/e49a2b2e-4c36-4c6a-bd1a-b5b065e63bb8</code>

以上是基本的api,consumer,plugin的基本介绍。

<code># 注册overseas_index api</code>

<code>curl -x post http://localhost:8888/apis/ -d "name=overseas_index" -d "upstream_url=http://10.182.20.128:8848/" -d "request_path=/stat/overseas" -d "strip_request_path=true"</code>

<code># 为海外版api注册key-auth插件</code>

<code>curl -x post http://localhost:8888/apis/overseas_index/plugins --data "name=key-auth"</code>

<code># 创建overseas_user 用户</code>

<code>curl -x post http://localhost:8888/consumers/ -d "username=overseas_test"</code>

<code># 为overseas_test创建权限验证</code>

<code>curl -x post http://localhost:8888/consumers/overseas_test/key-auth -d ""</code>

<code># 尝试查询海外版指标接口</code>

<code>curl -x post https://10.182.20.127/stat/overseas/realtime -d "app_id=53ace32656240b11c2071b1a" -d "date=2015-07-22" -h "apikey: 5e3b2a7a735744b39aeea9ebc2de1f01" --insecure</code>

<code># 给测试api</code>

<code>curl -x post https://10.182.20.128/test -d "app_id=53ace32656240b11c2071b1a" -d "date=2015-07-22" -h "apikey: 5e3b2a7a735744b39aeea9ebc2de1f01" --insecure</code>

设置acl插件

<code># 给另外一个testapi加上权限验证插件,现在任何通过认证的用户都可以调用此api</code>

<code># 这不是我们所希望的,所以需要加入acl控制</code>

<code>curl -x post http://localhost:8888/apis/testapi/plugins --data "name=key-auth"</code>

<code># 为用户overseas_test创建acl群组:overseas_user</code>

<code>curl -x post http://localhost:8888/consumers/overseas_test/acls \</code>

<code>--data "group=overseas_user"</code>