快速开发你的小服务
前言
现在微服务盛行,很多项目依赖一些协同工作小而自治的服务。那么对于python,虽然有grpc、nameko这样的微服务框架,或者Flask、Django这样的web框架。我们是否可以编写一个轻量可复用的服务框架呢?
准备
python: 2.7+/3.6+
主要库:PyMySQL、redis、DBUtils、requests、supervisor、urllib3、Werkzeug、gevent、gunicorn
简介
我们主要使用Werkzeug、gevent、gunicorn来实现。
Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等,例如 Flask 框架就是一 Werkzeug 为基础开发的.
Gevent是一个基于greenlet的Python的并发框架,以微线程greenlet为核心,使用了epoll事件监听机制以及诸多其他优化而变得高效。
Gunicorn是一个unix上被广泛使用的高性能的Python WSGI UNIX HTTP Server。和大多数的web框架兼容,并具有实现简单,轻量级,高性能等特点。
一般微服务都是本质上是一些数据库简易CRUD操作的集合,一个服务基本包含数据库连接、日志记录,业务逻辑等。那么我们看看这些的基本实现.
实现
数据库连接
mysql我们使用pymysql和DBUtils做一个连接池,缓存我们使用redis.
操作数据库我们也使用了日志记录,日志记录实现请看下段。
1 | #!/usr/bin/env python |
日志记录
使用logging模块,配置轮转
1 | #!/usr/bin/env python |
请求返回
我们编写了一个expose装饰器来做路由:
1 | #!/usr/bin/env python |
对应url_map绑定到环境:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : app.py
# @Author : cgDeepLearn
# @Create Date : 2020/11/12-2:47 下午
from gevent import monkey
monkey.patch_all()
from traceback import format_exc
from werkzeug.wrappers import Request, Response
from werkzeug.exceptions import HTTPException, NotFound, MethodNotAllowed, BadRequest
from server import g_server
from utils.log import logger
from decorator import url_map
def g_app(environ, start_response):
request = Request(environ)
adapter = url_map.bind_to_environ(environ)
try:
endpoint, values = adapter.match()
response = getattr(g_server, endpoint)(request, **values)
except (NotFound, MethodNotAllowed, BadRequest) as e:
response = e
except HTTPException as e:
response = e
except:
Response()
response = Response('Uncatched Error')
logger.error('app uncatched error, exception:%s', format_exc())
return response(environ, start_response)请求/test响应示例
1 | #!/usr/bin/env python |
如果我们想要新增一个路由,只需再server模块增加对应处理即可
业务逻辑简答示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @File : api.py
# @Author : cgDeepLearn
# @Create Date : 2020/11/16-3:40 下午
import datetime
import random
class TestApi(object):
def __init__(self, req_data):
self.req_data = req_data
def process(self):
"""
处理返回
"""
results = [-1, 0, 1]
res = {
'timestamp': datetime.datetime.now().timestamp(),
'result': random.choice(results)
}
return res
gunicorn 配置
我们使用gevent协程工作方式,配置对应服务器ip、端口、进程数等参数。
1 | #!/usr/bin/env python |
启动脚本
脚本里使用gunicorn启动服务、通过kill命令停止、重载或者重启服务。
1 | !/bin/sh |
请求示例
请求:
1
curl http://127.0.0.1:10001/test -d '{"order_id":12345}'
返回:
1
{"order_id": 12345,"uuid": "e3bd4a7e-35eb-11eb-bd7e-5254008f07ce","err_msg":"ok","err_code":0,"data": {"timestamp":1589193745,"result":1}}
小结
以上我们使用Werkzeug、gevent、gunicorn实现了一个轻量的python服务,修改配置、添加对应业务逻辑即可快速开发一个业务对应的微服务。项目git代码: https://github.com/cgDeepLearn/pyserver
此外
- 我们还可以使用
supervisor来控制服务的监控拉起。 - 使用
docker来进行容器化管理 使用cookiecutter来生成可配置的代码
使用
serviceMesh来进行服务注册发现