在我當前所作的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)
改造完成!