WhyApacheThrift
最近の必要性のプロジェクトに統合されるので、Pythonで書かれた機械学習アルゴリズムに来るが、SpringCloudテクノロジー・スタックの主な用途の私の後端は。だから、言語の異種実装の間の通信の選択に直面。ビジネスロジックはこれであるので
これの主な部分はほとんどあり長いのWebServer PYをパッケージ化サービスを提供したり、使用メッセージミドルウェアに選択できるが、メッセージ通信モデルの真ん中でもありますようとして、多くの方法が達成するために要求に応答して、2-3を達成することです片道、そのパブリケーション・サブスクリプションが、また、上記のビジネスニーズを達成するために
プロジェクトの実施は、選択シンプルで、粗が直接、次のコードのように、書き込みサーバ、ソケット実装とJavaクライアント、両者の間の異種通信へのソケットでソケットプログラミング、PYを使用し、このような事実に始まりました2は、ローカルで実行している場合、当事者間の通信速度をすることができますが、整理がパッケージ化され、両者間の通信回線にリリースされたときに、私は鏡に彼を作る場合でも、ナインが必要
リクエストは確かに受け入れられない9秒で、必要
InetAddress localhost = InetAddress.getByName("192.168.88.1");
Socket socket = new Socket(localhost.getHostName(), 9999);
OutputStream outputStream = socket.getOutputStream();
InputStream inputStream = socket.getInputStream();
// 向py发送消息
PrintStream out = new PrintStream(outputStream);
// 发送内容
out.print("hi python");
// 获取消息
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String targetName = bufferedReader.readLine();
System.err.println("获取返回的消息 " + targetName);
import socket
import time
# 建立一个服务端
server = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(('localhost',9999)) #绑定要监听的端口
server.listen(5) #开始监听 表示可以使用五个链接排队
while True:# conn就是客户端链接过来而在服务端为期生成的一个链接实例
conn,addr = server.accept() #等待链接,多个链接的时候就会出现问题,其实返回了两个值
print(conn,addr)
while True:
try:
data = conn.recv(1024) #接收数据
print('recive:',data.decode()) #打印接收到的数据
conn.send(data.upper()) #然后再发送数据
time.sleep(3)
except ConnectionResetError as e:
print('关闭了正在占线的链接!')
break
conn.close()
実際には、問題のほとんどは、我々は今、出会いの前任者ががあるかもしれない実際には、業界を達成するため、需要に同じように、遭遇した多く、Apacheのトップレベルプロジェクトスリフトは、この問題に対する完璧なソリューション、および通信の速さ、影響することができおよび安定性は、スーパーに最適です
スリフトプロフィール
Apacheの倹約はログインfacebookのApacheに寄贈され、今では倹約は倹約の意味、またAペーストップレベルのプロジェクトで、倹約は基本的に、インタフェース記述言語とバイナリ通信プロトコルである、もともと言語間でサービスコールのサービスを実現するためにされて設計されました、 RPCは絶対に優れたフレームワークです
C#、(POSIX互換システムに基づいて)C ++、カプチーノ、ココア、デルファイ、アーラン、ゴー、ハスケル、ジャワ、Node.jsの、OCamlでは、PerlやPHP、PythonやRubyとSmalltalkの現在、倹約のような、多くの言語をされているサポート。
インストール
公式サイトのダウンロード:http://thrift.apache.org/download
ダウンロードコンパイラ
私たちは、自動的に私たちのためにアウトスリフトを使用して生成されたコードを使用して、最初に本当にだからなぜ?このコンパイラを使用し、はっきり、私達はちょうどこのコンパイルによって定義されたビジネスロジックに基づいて良いの.thriftファイルを必要とするということであるその[OK]を私たちのために、コンパイラどのようなコードの言語生成を伝えるために、構成ファイル、および使用をコンパイルし、スリフトフレームワークを自動的だろう我々のコードのために、またソケットにパッケージを含んで生成する当事者間のコーデックの論理的な通信、全体としてワンストップサービスであります
ので、Windowsのこの使用なので、ダウンロード.exeのコンパイラの最後の
環境変数を追加します
コードが完了するとした後、このステップは避けられないようなアイデアで生成されたコードは、そうでない場合は、このコマンドを見つけることができないと言うだろうしながら、
最初のピット:このコンパイラについて名前の変更、少数の以前のバージョンを削除するには、環境変数を追加して行きます
2回目のピット:あなたは倹約のバージョン番号がコンソールに表示されますが、アイデアが特定されていない入力した場合、コンピュータを再起動します
スリフトシステムアーキテクチャ
なぜルックスリフトシステムアーキテクチャそれ?スリフトは自動的にいくつかのテンプレートコードを生成するために私たちを助けるが、それでも手動でクライアントとサーバのコードをエンコードする必要があり、そのアーキテクチャのシステムを理解し、サーバーを見て、あなたの書き込みの場合であろうがクライアントコードも理解して読むことができ、次のシステムアーキテクチャでは、あなたのコード内のオブジェクトの構造は全てトレーサブルです
上に示したように、スリフトは、典型的なCSアーキテクチャである我々は(インタフェースDescriptionLanguage)言語IDLと呼ばれる倹約することができますが、サーバーとクライアント上の図は、異なる言語の開発を使用することができ、これらの二つの異なるサーバーサイドの言語の開発とどのようなクライアント間の通信に使用することはスリフトで実現すること
- YourCode:当社独自のビジネスコードです
- クライアントとサーバーが通信するオブジェクト:FooServiceClient
- フー・書き込み()/)(読み:これは、ソケットを介してデータの自動生成、当社のスリフトコードロジックパッケージ下部に送信することです
- TProtocol: 协议层, 在这一层中规定了数据传输使用的哪种协议
- TTransport: 传输层: 在这一层中规定了数传输的格式,比如需不需要进行压缩
- Underlying IO : 数据在网络中的IO交互
Thrift的传输协议
这种传输协议实际上就是规定了数据在网络上采用什么样的格式进行传输
- TBinaryProtocol : 以二进制格式进行传输
- TCompactProtocol: 对二进制数据进一步压缩的格式
- TJsonProtocol: json格式
- TSimpleJsonProtocol: 针对Json的只写协议
- TDebugProtocol: 简单易懂的文本格式, 常用于去 调试代码使用
Thrift的数据传输方式
- TSocket : 阻塞式的Socket 效率最低
- TFrameTransport: 在非阻塞应用服务中常用. 以Frame为单位进行传输
- TFileTransport: 以文本格式进行传输
- TMemoryTransport: 使用内存进行IO, 在java中的实现是 ByteArrayOutPutStream
Thrift支持的服务模型
这种服务类型说的就是服务端示例的类型, 有如下几种
- TSimpleServer: 简单的单线程服务模型
- TThreadPoolServer: 虽然是表中的阻塞式IO, 但是采用多线程模型处理
- TNonblockingServer: 多线程服务模型, 使用的是非阻塞IO常和TFramedTransport数据传输方式搭配使用
- THsHaServer: 引用线程池去处理, 采用的是半同步,半异步的模式, 针对不同类型的消息, 进行不同的处理, 比如对IO类型的消息异步处理, 对Handler的RPC远程过程调用进行同步处理
Thrift的数据类型
thrift不支持无符号数据类型
简单的数据类型:
名称 | 简介 |
---|---|
byte | 有符号字节 |
i16 | 16位有符号整数 |
i32 | 32位有符号整数 |
i64 | 64位有符号整数 |
double | 64位浮点数 |
string | 字符串类型 |
thrift的容器类型: (支持泛型)
- list: 表示一系列T类型的数据组成的有序列表, 元素可以重复
- set: 一系列T类型的数据组合成的无序集合, 元素不重复
- map: 一个字典结构, key为K类型, value为V类型,相当于java中的hashmap
结构体: 这个struct类似C语言中的结构体, 初衷也是将不同的数据聚合在一起,方便传输,经过编译器编译完成后其实就是java中的类
struct Student{
1:string name;
2:i32 age;
}
枚举类型
enum Gender{
MALE,
FEMALE
}
异常类型: thrift 支持异常类型表示服务端和客户端之间的通信所可能抛出来的异常, 并且我们可以在service中的方法上throws 异常, 用描述异常出现的时间,异常的类型
exception RequestException{
1:i32 coed
2: string reason
}
服务类型: 服务端和客户端通信使用到的接口 , 就好比java中的接口, 它是一系列方法的集合, thrift 会将service转换成客户端和服务端的框架的代码 , 定义形式如下
service MyService{
string ask(1:string name,2:i32 age)
}
类型定义: 可以像下面这样,使用类似C语言的语法为变量取别名, 转换成我们习惯的命名格式
typedef i32 int
typedef i64 long
常量const类型: thrift 同样支持常量的定义, 使用const关键字:
const string NAME="XXX"
命名空间类型: 关键字是 namespace , thrift的命名空间相当于java中的package, 实际使用上thrift也会将生成的代码放在这下面指定的包中
格式: namespace 语言 路径
实例: namespace java com.changwu.thrift.Demo
文件包含: 同样向C/C++那样,支持文件之间相互包含的操作. 在java中这个动作就是Import
include "global.thrift"
注释: thrift 中的注释有一下几种
// XXXX
# XXX
/*XXX*/
オプションと必須オプション、キーワードが必須およびオプションされ、対応するフィールドがオプションか必須表します
struct Student{
1:required string name;
2:optional string age;
}
リアル
スリフト書き込みファイル
我々は、ターゲット言語のコードを生成することを期待し、上記で定義された倹約ファイルを使用します
namespace java com.changwu.thrift
namespace py py.thrift
// 去别名字
typedef string String
typedef bool boolean
// 我们通过 .thrift文件 描述对象(struct), 方法(service), 类型, 异常等信息
struct Message {
1: optional String msg,
}
exception MyExcetion{
1:optional String message,
2:optional String callStack,
3:optional String date
}
service PersonService{
Message getResultFromPy(1:required String message) throws(1:MyExcetion e),
}
コード生成
ルートパスの下でよりGEN-javaディレクトリされるコマンドコード生成を実行した後、また、コードが生成されます
命令 thrift --gen 语言 .thrift文件路径
java实例: thrift --gen java src/thrift/data.thrift
py 实例: thrift --gen py src/thrift/data.thrift
あなたはこれらの2つのコマンドを実行した後、私たちはこの結果を得るでしょう
インポートの実行への依存
依存するJARパッケージ導入ランタイム
<!-- https://mvnrepository.com/artifact/org.apache.thrift/libthrift -->
<dependency>
<groupId>org.apache.thrift</groupId>
<artifactId>libthrift</artifactId>
<version>0.13.0</version>
</dependency>
コーディング
クライアントのJava実装を使用し、MessageServiceで私たちの上と言うことですサービスクラスの種類、内スリフトクライアントコード生成、
私たちが知ることができる上記スリフトのアーキテクチャを理解することにより、および一貫して、そのためのサンプルコード以下である必要はありTPROTOCOL TTransportビルドクライアントとサーバーを選択する必要がクリアされます
// 帮点端口号和超时时间
TTransport tTransport = new TFramedTransport(new TSocket("localhost",9999),600);
TProtocol protocol = new TCompactProtocol(tTransport);
MessageService.Client client = new MessageService.Client(protocol);
try{
// 打开socket
tTransport.open();
// 发送
Message p = client.getResultFromPy("张三123");
System.out.println("结果: "+p.getMsg());
}catch (Exception e){
e.printStackTrace();
}finally {
tTransport.close();
}
PYエンドサーバーの実装
ここで、特定のメッセージ・コールバック・ビジネス・ロジックを受信した場合Pyは第一の端部に、先に定義されたインタフェースを実装する、定義されています
class MessageServiceImpl:
def getResultFromPy(self, msg):
print("获取到msg = " + msg)
message = ttypes.Message()
message.msg = 'hello java'
return messag
書き込みサーバ側
書き込みサーバとクライアントのコードは、実際には、前述のスリフトアーキテクチャの仕様に従ってください、そして第二に、使用アイデアへのニーズはPYに関連付けられた古道具図書館に設置しました
ダウンロードhttp://www.apache.org/dyn/closer.cgi?path=/thrift/0.13.0/thrift-0.13.0.tar.gz
オープン地元の解凍には、次に見つけlibに入り、PYディレクトリ内に見つけるPY PYのサポートをインストール
コマンドを実行します。
python setup.py install
from thrift.transport import TTransport
from thrift.protocol import TCompactProtocol
from thrift.server import TServer
from py.thrift import MessageService
from MessageServiceImpl import MessageServiceImpl
try:
# handler就是我们对 ThriftService的实现
personServiceHandler = MessageServiceImpl()
# Foo read()/write() 被Thrift生成在 MesageServive中
processor = MessageService.Processor(personServiceHandler)
# TSocket TProtocol 和 Transport 从上面下载的类库导入进来
# 这三者的作用在上面的架构图上也能提现出来
serverSocket = TSocket.TServerSocket(host="127.0.0.1",port=9999)
transportFactory = TTransport.TFramedTransportFactory()
protocolFactory = TCompactProtocol.TCompactProtocolFactory()
# py提供了四种Server , TThreadPoolServer TServer THeaderProtocolFactory
server = TServer.TThreadPoolServer(processor,serverSocket,transportFactory,protocolFactory)
print(">>>>>>>>>>>>>>>>>>服务端启动>>>>>>>>>>>>>>>>>>>>")
server.serve()
except Thrift.TException as ex:
print("%s" % ex.message)
[OK]を、これまでのコードを書き終えたが、異種の通信の魅力を体験して、それを実行してみてください