学习一下thrift。
环境
mac m1,go 1.20,php 7.4,thrift 0.18.1
要学习thrift,第一步得先安装
$ brew install thrift
学习的计划是用go作为server,php作为client,通过thrift的方式完成一次请求demo。
建个目录thrift_demo,然后在目录里完成go相关的操作。
先定义thrift文件,文件名就叫helloworld.thrift。
namespace go thrift_demo
service HelloWorld {
string SayHello()
}
定义好之后,执行thrift指令来生成go代码
$ thrift --gen go helloworld.thrift
执行完成后,在当前目录就会生成gen-go目录,里面是thrift自动生成的go代码文件。
用go做server,那就新建一个server.go文件,作为handler,来实现helloworld.thrift里定义的方法。
package main
import (
"context"
"fmt"
"github.com/apache/thrift/lib/go/thrift"
"thrift_demo/gen-go/thrift_demo"
)
type HelloWorldHandler struct{}
func (h *HelloWorldHandler) SayHello(ctx context.Context) (string, error) {
return "Hello, world!", nil
}
func main() {
handler := &HelloWorldHandler{}
processor := thrift_demo.NewHelloWorldProcessor(handler)
serverTransport, err := thrift.NewTServerSocket(":9090")
if err != nil {
panic(err)
}
transportFactory := thrift.NewTBufferedTransportFactory(1000000)
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory)
fmt.Println("Starting the server...")
if err := server.Serve(); err != nil {
panic(err)
}
}
上面是server.go的代码,除了实现HelloWorldHandler之外,还启动了一个server来监听9090端口。
下面接着来写client,先用go写一版试试。
package main
import (
"context"
"fmt"
"github.com/apache/thrift/lib/go/thrift"
"thrift_demo/gen-go/thrift_demo"
)
func main() {
transport, err := thrift.NewTSocket("localhost:9090")
if err != nil {
panic(err)
}
defer transport.Close()
if err := transport.Open(); err != nil {
panic(err)
}
protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()
client := thrift_demo.NewHelloWorldClientFactory(transport, protocolFactory)
result, err := client.SayHello(context.Background())
if err != nil {
println(err.Error())
panic(err)
}
fmt.Println(result)
}
server和client都写完后,来执行一下看看
$ go run server.go
先启动server端,再启动client
$ go run client.go
Hello, world!
能看到返回的输出就是HelloWorldHandler里实现的sayHello()方法的输出,请求链路是通的。
下面就来写一下php client。
首先需要用thrift生成php代码
$ thrift --gen php helloworld.thrift
执行完成后,会生成gen-php目录已经相关的php代码文件
这里需要将gen-php目录拷贝出来,放到php代码目录下面,然后再编写php版本的client.php
<?php
namespace ttt\php;
error_reporting(E_ALL);
require_once "vendor/autoload.php";
require __DIR__."/gen-php/HelloWorldClient.php";
use \Thrift\ClassLoader\ThriftClassLoader;
use Thrift\Protocol\TBinaryProtocol;
use Thrift\Transport\TBufferedTransport;
use Thrift\Transport\TSocket;
use Thrift\Exception\TException;
$GEN_DIR = dirname(__FILE__).'/gen-php';
$loader = new ThriftClassLoader();
$loader->registerNamespace('Thrift', __DIR__.'/vendor/apache/thrift/lib/php/lib');
$loader->registerDefinition('Services', $GEN_DIR);
$loader->register();
try {
$socket = new TSocket('localhost', 9090);
$trans = new TBufferedTransport($socket, 1024, 1024);
$protocol = new TBinaryProtocol($trans);
$client = new \HelloWorldClient($protocol);
$trans->open();
$ret = $client->SayHello();
var_dump($ret);
} catch (\TException|\Exception $e) {
var_dump($e->getMessage());
}
写完之后执行一下
$ php client.php
Warning: require(./HelloWorldIf.php): failed to open stream: No such file or directory in /Users/myStudy/gen-php/HelloWorldClient.php on line 8
Fatal error: require(): Failed opening required './HelloWorldIf.php' (include_path='.:/opt/homebrew/Cellar/php@7.4/7.4.24_1/share/php@7.4/pear') in /Users/myStudy/gen-php/HelloWorldClient.php on line 8
报错了,意思是HelloWorldClient.php里没有找到依赖文件,把它需要的给它补上。
修改gen-php/HelloWorldClient.php文件,增加如下内容
require 'HelloWorldIf.php';
require 'HelloWorld_SayHello_args.php';
require 'HelloWorld_SayHello_result.php';
然后再次运行client
$ php client.php
string(13) "Hello, world!"
成了。
其中,可能需要解决一些依赖问题,php的包可以使用
"apache/thrift": "^0.18.1"
go可以使用
require github.com/apache/thrift v0.18.1