• 微服务性能优化之thrift改造


    在我当前所做的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)

    改造完成!

  • 相关阅读:
    关于Linux静态库和动态库的分析
    某个表格不知道被哪个Session 锁住了,及如何解锁
    如何降低索引的clustering_factor
    Oracle Logminer 查找日志信息
    使用“alter index ××× monitoring usage;”语句监控索引使用与否(转载secooler) 转
    Oracle提高查询效率的解析
    数据库flash_recovery_area满导致数据库启动报错ORA03113错误
    ora错误代码汇总
    Oracle BBED 工具介绍
    oracle BBED 直接修改数据库block块
  • 原文地址:https://www.cnblogs.com/victorwu/p/8543903.html
Copyright © 2020-2023  润新知