微服务性能优化之thrift改造

在我当前所作的web项目中,采用先后端分离模式前端经过Django 提供restful接口,后端采用微服务架构,微服务之间的调用采用jsonrpc,因为微服务之间的调用很频繁,致使前端获得的响应很慢,因此就不得不作性能优化。前端

JSON-RPC是一种基于JSON的跨语言远程调用协议。比xml-rpc、webservice等基于文本的协议传输数据格小;可是JSON格式的解析开销太大。python

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/grpcgit

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/github

经过实践代表,thrift的性能是最好的,Thrift性能明显优于gRPC,性能差距也在两倍以上,因此接下来说解thrift rpc的改造。web

性能优化以前使用的jsonrpc:apache

# 须要安装django-json-rpc
pip install django-json-rpc
# 配置文件添加jsonrpc到INSTALLED_APPS
INSTALLED_APPS = [                                                                                                                                                                                                                                                     ...
   'jsonrpc',                                                                                                                                                                                                                                                                     ...
]
url.py配置路由:
django

 

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以下 :json

服务端编写:# 须要安装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)

改造完成!

相关文章
相关标签/搜索