在我当前所做的web项目中,采用前后端分离模式前端通过Django 提供restful接口,后端采用微服务架构,微服务之间的调用采用jsonrpc,由于微服务之间的调用很频繁,导致前端得到的响应很慢,所以就不得不做性能优化。
JSON-RPC是一种基于JSON的跨语言远程调用协议。比xml-rpc、webservice等基于文本的协议传输数据格小;但是JSON格式的解析开销太大。
GRPC:GRPC是一个高性能、通用的开源RPC框架,由Google主要面向移动应用开发并基于HTTP/2协议(注意是HTTP/2协议,不是我们常使用的HTTP 1_1。HTTP/2协议详细的介绍可以参见官方地址:https://http2.github.io/)标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。为了支持GRPC的跨语言性,GRPC有一套独立存在IDL语言。不过由于GRPC是Google的开源产品,在信息格式封装方面Google主要还是推广的自己的ProtoBuf,所以GPRC是不支持其他信息格式的(至少ProtoBuf效率是大家有目共睹的)。关于GRPC详细的使用介绍,可以参见官方地址:https://github.com/grpc/grpc
Thrift:Thrift是Facebook的一个开源项目,后来进入Apache进行孵化。Thrift也是支持跨语言的,所以它有自己的一套IDL。目前它支持几乎所有主流的编程语言:C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, OCaml and Delphi and other languages。Thrift可以支持多种信息格式,除了Thrift私有的二进制编码规则和一种LVQ(类似于TLV消息格式)的消息格式,还有常规的JSON格式。Thrift的网络协议建立在TCP协议基础上,并且支持阻塞式IO模型和多路IO复用模型。我们将在后文详细讲解Apache Thrift的使用。Thrift也是目前最流行的RPC框架之一,从网络上各种性能测试情况开,Thrift的性能都是领先的。Thrift的官网地址为:http://thrift.apache.org/
通过实践表明,thrift的性能是最好的,Thrift性能明显优于gRPC,性能差距也在两倍以上,所以接下来讲解thrift rpc的改造。
性能优化之前使用的jsonrpc:
# 需要安装django-json-rpc
pip install django-json-rpc
# 配置文件添加jsonrpc到INSTALLED_APPS
INSTALLED_APPS = [ ...
'jsonrpc', ...
]
url.py配置路由:
from jsonrpc import jsonrpc_site
urlpatterns = [
url(r'^rpc/$', jsonrpc_site.dispatch, name='jsonrpc_mountpoint'),
]
views.py编写rpc函数:
from jsonrpc import jsonrpc_method
from jsonrpc.proxy import ServiceProxy
from user.models import ServiceProvidersAuth
@jsonrpc_method('user.is_provider_auth')
def get_provider_auth(request, user_id):
"""
Get provider is authentication by user id.
"""
provider = ServiceProvidersAuth.objects.filter(user_id=user_id)
if provider.exists():
return Response(True)
else:
return Response(False)
改造为高性能的thrift rpc如下 :
服务端编写:# 需要安装thrift 和django-thrift
pip install thrift
pip install django-thrift
# 修改配置文件settings.py
INSTALLED_APPS = [
# other apps
'django_thrift',
# and so on
]
# 指定thrift路径和服务
THRIFT = {
"FILE": "idl/thrift/user.thrift",
"SERVICE": "UserManager"
}
在idl/thrift/user.thrift文件里定义thrift的结构:
service UserManager{
bool get_provider_auth(1:i32 user_id)
}
在views.py中定义thrift 的具体调用(函数名、参数和返回值类型和thrift文件中定义的一致):
from django_thrift.handler import create_handler
from user.models import ServiceProvidersAuth
handler = create_handler()
@handler.map_function('get_provider_auth')
def get_provider_auth(user_id):
provider = ServiceProvidersAuth.objects.filter(user_id=user_id)
if provider.exists():
return True
else:
return False
启动thrift rpc命令:
python manage.py runrpcserver --port 9000
客户端编写:
在客户端的thrift的文件中需要拷贝要调用的thrift结构,即:
service UserManager{
bool get_provider_auth(1:i32 user_id)
}
其他服务调用,编写通用请求thrift函数utils.py:
import logging
import thriftpy
from django.conf import settings
from thriftpy.rpc import make_client
logger = logging.getLogger('django')
def request_thrift(service, method, url, port, *args, **kwargs):
try:
thrift = settings.THRIFT['FILE']
service = getattr(thriftpy.load(thrift, module_name=thrift.replace('.', '_')), service)
client = make_client(service, url, port)
msg = getattr(client, method)(*args, **kwargs)
return msg
except Exception as ex:
logger.error(str(ex))
然后调用:
# 导入utils模块
from user import utils
ret = utils.request_thrift('UserManager', 'get_provider_auth', '127.0.0.1', 9000, 1)
改造完成!
来源:oschina
链接:https://my.oschina.net/u/4352420/blog/4042260