Python微服务框架nameko的简单使用
推荐一款 Python 微服务框架 - Nameko
微服务框架有Istio、Dubbo和nameko三种:
一、Istio
Istio是一个用来连接、管理和保护微服务的开放平台,使用Istio可以建立已部署服务网络,且Istio具备负载均衡、服务间认证、监控等功能。
二、Dubbo
Dubbo是一个利用同步通信实现的分布式微服务框架,其致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。
三、nameko
nameko是一个利用异步通信方式实现的微服务框架,其采用RabbitMQ消息队列作为消息中间件,原理简单,使用方便。
在后端开发方面,Java的使用呢要远比Python广泛,所以Java的微服务框架非常流行,但Python的微服务框架却很少有人问津。在大多数需要微服务的场合下直接用Java的各种工具就可以解决问题,但如果业务代码使用Python写的,那么使用Java工具就不太方便了。
其实Python也有自己的微服务框架,其中用的最多的就是nameko,nameko框架轻便,使用简单,易上手,是一个很不错的微服务框架。
首先假设要做一款简化版的微信产品,它只有如下几个功能。那么你的初期系统设计应该是这样的:
(1)微信单体架构
随着时间的迁移,跨年夜,同一时刻,很多人都在发朋友圈,朋友圈接口访问量很大,服务器访问峰值瞬间冲顶,那么我们可以开始做集群操作,也就是整一个服务器做集群操作。
那么我们的注册登录接口、支付接口、聊天接口也有了一个复制集,但此刻这几个接口其实并没有很大的访问量,那我们能不能只将朋友圈的接口做扩容呢?答案当然是可以的,基于微服务架构进行扩容。
(2)微服务架构
直接水平扩展朋友圈服务,如下图,峰值压力有所缓解。
然而在各个功能拆解成一个个的服务之后,由客户端直接访问各个微服务,这样就直接将我们的服务暴露了出来,客户端也需要定制相应的访问策略。这样的设计还是没有那么友好。那么,我们能不能将所有微服务统一到一起呢?且看下图:
(3)微服务架构Plus
在这张示例图中,多了一个API Gateway模块,那API网关是用来干嘛的呢?一般情况下 API 网关有以下任务:路由,安全,限流,缓存,日志,监控,重试,熔断等,然后服务层就纯粹的做业务,也能够很好的保证业务代码的干净,不用关心安全,压力等方面的问题。
(4)微服务的特征与优势
微服务特征:单一职责;轻量级的通信;隔离性,运行在自己的进程中,不会相互干扰;有自己的数据,数据的独立性,每个微服务都有自己的数据库;技术的多样性,选用适合的技术做合适的事。
一个微服务就负责某一个职责,就像朋友圈服务,它就只负责朋友圈的增删查功能,与其他服务独立开来,可以选用不同的技术语言,来满足不同的需求。
微服务的优势:独立性、敏捷性、技术栈灵活、高效团队。
(5)微服务的不足
额外的工作、数据一致性、沟通成本、debug 单元测试困难、需要额外工作。
微服务架构最重要的就是使用什么方式进行服务间通信(也称作服务调用),按照通信方式的不同,主要可以分为同步通信和异步通信两种方式:
同步调用比较简单,一致性强,但是容易出调用问题,性能体验上也会差些。同步通信最常用的两种协议是RESTful和RPC,而目前使用最广泛,最有名的两种微服务框架Spring Cloud和Dubbo分别使用了RESTful和RPC协议。RESTful和RPC两种协议各有优势,具体使用要看业务场景。
Dubbo框架是一个非常流行的采用同步通信的分布式微服务框架,下图就是Dubbo框架的工作原理图:
首先一个微服务应用程序需要有服务的生产者和服务的消费者,另外还需要一个注册中心(常见的有zookeeper和RabbitMQ等)来管理和调度服务。
微服务架构的程序运行的一般步骤为:
(1)服务提供方,即生产者启动服务,并将服务提交到注册中心注册服务。
(2)服务需求方,即消费者连接到注册中心,向注册中心发出请求,申请需要的服务。
(3)注册中心根据消费者发出的请求来调度服务,将对应的服务提供者(生产者)的信息发送给消费者。
(4)消费者和生产者之间建立连接,消费者调用服务。
(5)记录服务调用过程中的信息。
异步通信一般通过消息中间件来进行服务间通信,消息中间件能为调用之间提供的缓冲,确保消息积压不会冲垮被调用方,同时能保证调用方的服务体验,继续干自己该干的活,不至于被后台性能拖慢。不过需要付出的代价是一致性的减弱。
Nameko框架就是一个采用异步通信方式的微服务框架,采用RabbitMQ消息队列作为消息中间件,原理非常简单,使用起来也很方便。
Nameko采用RabbitMQ作为注册中心,所以使用Nameko必须要先安装RabbitMQ。
以docker容器的方式运行RabbitMQ是最为简便快捷的方式,两行命令就搞定了,这里介绍如何使用docker运行RabbitMQ。
第一步:从DockerHub拉取rabbitmq镜像
docker pull rabbitmq:management
第二步:运行RabbitMQ容器
docker run -d --hostname my-rabbit --name rabbit -p 15672:15672 -p 5672:5672 rabbitmq:management
参数分析如下docker run -d
--hostname my-rabbit
--name rabbit
-p 15672:15672 控制台Web访问端口号
-p 5672:5672 应用访问端口
rabbitmq:management
如果需要设置用户名和密码,则使用这条命令
docker run -d --hostname my-rabbit --name rabbit -e RABBITMQ_DEFAULT_USER=user -e RABBITMQ_DEFAULT_PASS=password -p 15672:15672 -p 5672:5672 rabbitmq:management
参数分析如下docker run -d
--hostname my-rabbit
--name rabbit
-e RABBITMQ_DEFAULT_USER=user
-e RABBITMQ_DEFAULT_PASS=password
-p 15672:15672 控制台Web访问端口号
-p 5672:5672 应用访问端口
rabbitmq:management
我运行容器时没有设置用户名和密码,所以使用用户名guest,密码guest登录。
http://localhost:15672/
http://192.168.1.10:15672/
在浏览器中通过下面的连接进入到MQ后台Web管理页面
登录成功界面
pip install nameko
create_service.py发布服务,服务名称为“helloservice”。
from nameko.rpc import rpc
class hello_service:
name = "helloservice"
@rpc
def hello(self):
print("hello world")
@rpc
def hi(self):
print("my name is lucy")
使用nameko框架的run命令启动微服务。
nameko run create_service --broker amqp://guest:[email protected]
invoke_service.py调用服务进行消费。
from nameko.standalone.rpc import ClusterRpcProxy
CONFIG = {'AMQP_URI': "amqp://guest:[email protected]"}
def compute():
with ClusterRpcProxy(CONFIG) as rpc:
rpc.helloservice.hello()
if __name__ == '__main__':
compute()
运行invoke_service.py调用服务后在命令行打印出“hello world”,服务被成功调用。
自定一个类,使用name属性定义服务的名称为generate_service。然后使用装饰器rpc注册服务中具体的方法。
from nameko.rpc import rpc
class GenerateService(object):
# 定义微服务名称
name = "generate_service"
@rpc
def hello_world(self, msg):
print('hello,I am been called by customer(消费者),返回消息:{}'.format(msg))
# 返回结果
return "Hello World!I Am a msg from producer!"
使用nameko命令在终端将目标文件中的服务注册到MQ中。
# 注册服务
nameko run producer_service --broker amqp://guest:[email protected]:5672/
参数分析如下
producer_service:目标文件名称
guest:guest:MQ用户名及密码
ip地址:5672:MQ服务器ip地址及应用端口号
为了演示方便,这里使用Flask编写一个简单的API。
(1)首先,定义MQ连接信息
(2)然后,编写一个API接口,请求方式为GET。
(3)最后,使用nameko中的ClusterRpcProxy拿到消费者对象去调用服务中的具体方法。
from flask import Flask
from nameko.standalone.rpc import ClusterRpcProxy
app = Flask(__name__)
# MQ配置
config_mq = {'AMQP_URI': "amqp://guest:[email protected]"}
@app.route('/hello_world', methods=['GET'])
def call_service():
with ClusterRpcProxy(config_mq) as rpc:
# 消费者调用微服务(生产者),获取服务(生产者)的返回值
# rpc.服务名.方法名
result = rpc.generate_service.hello_world(msg="xag msg")
# 返回结果
return result, 200
if __name__ == '__main__':
app.run(debug=True)
使用Postman调用上面的API接口,就能完成消费者调用生成者服务中的方法,拿到返回结果的完整流程。
http://127.0.0.1:5000/hello_world。
上面以Flask为例讲解了微服务的搭建的完整流程,如果是其他Web框架(比如Django、FastAPI等)集成微服务流程是类似的。