31

python后端架构

 5 years ago
source link: https://studygolang.com/articles/14116?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

最近在做一个在线平台,架构思路如下

架构演进:1、MVC  2、服务拆分 3、微服务架构 4、领域驱动设计

1、MVC

这个阶段主要是快速实现产品,没考虑其他的,设计之初划分多个app,app内高类聚,app之间低耦合,DB表设计好了之后,实现view层功能需求,利用Django来快速实现功能,后端有许多预留设计,避免产品逻辑的变更带来整个表结构的变动,架构如下图;

R3eeMzJ.png!web

MVC架构

nginx是负载均衡,通过权重法,把请求发送到多个Django服务(其实中间还有一个uwsgi),如果是静态请求,nginx直接返回给客户端,如果是其他请求,通过uwsgi传给Django,Django拿到请求,处理响应请求。耗时大的需要异步的,我们用celery处理,使用mysql作为数据库,redis作为缓存,加快请求的响应,减轻mysql负担,同时还有实时消息通知的需要使用了Nginx Push Module。

问题以及处理:

1、Django并不像tornado一样,对并发很支持,Django并发性能差,采用uwsgi+nginx+gevent实现高并发。

2、redis连接数过多,导致服务挂掉,使用redis-py自带的连接池来实现连接复用

3、mysql连接数过多,使用使用djorm-ext-pool

4、Celery配置gevent支持并发任务

5、celery配合rabbitmq任务队列实现任务的异步调度执行

Celery是一个分布式的任务队列。它的基本工作就是管理分配任务到不同的服务器,并且取得结果。至于说服务器之间是如何进行通信的?这个Celery本身不能解决。所以,RabbitMQ作为一个消息队列管理工具被引入到和Celery集成,负责处理服务器之间的通信任务。

随着开发的功能需求越来越多,Django下的app也越来越多,这就带了发布上的不方便,每次发布版本都需要重启所有的Django服务,如果发布遇到问题,只能加班解决了。而且单个Django工程下的代码量也越来越多,不好维护。

2、服务拆分

前面设计的app内高类聚,app之间低耦合是为服务拆分做铺垫的,首先先把公用的代码抽离出来,实现一个公用的库,其他的还是公用。估计当数据量增加后,要对redis以及mysql进行优化,可以分库分表,后续还需要拆分业务,这个要看原来的代码整洁度和互相依赖程度。

JZBNv2V.png!web

service separation

Nginx Push Module,长连接最大数量不够,使用Tornado + ZeroMQ实现了tormq服务来支撑消息通知。

问题:

随着业务拆分,继续使用Nginx维护配置非常麻烦,经常因为修改Nginx的配置引发调用错误。每一个服务都有一个完整的认证过程,认证又依赖于用户中心的数据库,修改认证时需要重新发布多个服务。

前面二层的架构均已实现,后续的微服务以及领域驱动设计由于我还未涉及到(我之前工作是使用Java做的微服务),所以在此贴出一位python开发工程师的解决办法。

3. 微服务架构

maqmmiQ.jpg!web

Microservices

首先是在接入层引入了基于OpenResty的Kong API Gateway,定制实现了认证,限流等插件。在接入层承接并剥离了应用层公共的认证,限流等功能。在发布新的服务时,发布脚本中调用Kong admin api注册服务地址到Kong,并加载api需要使用插件。

为了解决相互调用的问题,维护了一个基于gevent+msgpack的RPC服务框架doge,借助于etcd做服务治理,并在rpc客户端实现了限流,高可用,负载均衡这些功能。

在这个阶段最难的技术选型,开源的API网关大多用Golang与OpenResty(lua)实现,为了应对我们业务的需要还要做定制。前期花了1个月时间学习OpenResty与Golang,并使用OpenResty实现了一个短网址服务shorturl用在业务中。最终选择Kong是基于Lua发布的便利性,Kong的开箱即用以及插件开发比较容易。性能的考量倒不是最重要的,为了支撑更多的并发,还使用了云平台提供的LB服务分发流量到2台Kong服务器组成的集群。集群之间自动同步配置。

饿了么维护一个纯Python实现的thrift协议框架thriftpy,并提供很多配套的工具, 如果团队足够大,这一套RPC方案其实是合适的,但是我们的团队人手不足,水平参差不齐,很难推广这一整套学习成本高昂的方案。最终我们开发了类Duboo的RPC框架doge,代码主要参考了weibo开源的motan。

4. 领域驱动设计

ArABNvA.jpg!web

domain driven design(ddd)

在这一架构中我们尝试从应用服务中抽离出数据服务层,每一个数据服务包含一个或多个界限上下文,界限上下文类只有一个聚合根来暴露出RPC调用的方法。数据服务不依赖于应用服务,应用服务可以依赖多个数据服务。有了数据服务层,应用就解耦了相互之间的依赖,高层服务只依赖于底层服务。

出处: https://zhu327.github.io/2018/07/19/python/后端架构演进/


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK