接口定义语言idl——thrift

thritf

thrift是facebook开元的接口定义语言IDL(Interface Definition Languge),用于进行跨语言的接口定义从而实现不同语言之间的远程通讯。

不同的开发语言使用idl定义接口都会生成其本身的语法接口,idl忽略的语言的差异从而实现了远程调用。每个idl都有自己独特的语言法和工具,用于将自身代码生成其他语言的代码。

thrift、protobuf也提供了自己的工具将该语法编译成Java,python,Go等语言的代码,同时生成的代码中有构建server端与client端的方法,通过方法方法构建server服务器与client客户端,那么任意server和cliet都能通讯。

thrift的核心原理是序列化和反序列化,序列化就是将数据转化为字节流,反序列化就是将字节流恢复为数据。


namespace java demostruct addStore{1:i32 id2:string storeName3:i32 type4:string uuid5:string identitionTime6:string createAt7:i32 status
}struct delete{1:i32 id
}struct update{1:i32 id2:string storeName3:i32 type4:string uuid5:string identitionTime6:string createAt7:i32 status
}struct getStore{1:i32 id2:string storeName3:i32 type4:string uuid5:string identitionTime6:string createAt7:i32 status
}service storeInterface{i32 addStore(1:addStore req)i32 delete(1:delete req)i32 update(1:update req)list<getStore >getStore(1:i32 id 2:string uuid)
}

上述使用thrift定义了storeInterface接口,其中需要注意的是namespace声明了生成的语言为java。

thrift生成工具为thrift,如下所示:

在这里插入图片描述

kitex -module kitexdemo ./demo.thrift

需要注意的是namespace必须是要生成语言的表示,后一位是文件夹名
在这里插入图片描述

thrift -r --gen java demo.thrift

在这里插入图片描述

-r表示递归生成,--gen java表示生成Java代码,该命令会生成一个gen-java目录存放生成的代码。

在这里插入图片描述

thrift命令默认是在当前文件下生成,也可以使用-o来指定目录,-out更多命令使用thrift -help查看。

将生成的源码移到maven构建的源码目录,如下

在这里插入图片描述
打开文件发现全是报错

在这里插入图片描述
报错原因是在生成代码时只生成了源码而没有引入包,源码中import关键字都没有出现。解决方案也很简单查询thrift生成源码是需要哪些工具包,在maven中引入然后刷新pom文件即可。

https://mvnrepository.com
在这里插入图片描述在这里插入图片描述

也可以直接在idea中操作,鼠标点击红色报错Add Maven Dependency

在这里插入图片描述

Java实现

使用命令行只生成了代码和测设包名,要实际应用到maven中还需要改包名和引入依赖,如下

  1. 目录分层

在这里插入图片描述

  1. 引包引依赖

在这里插入图片描述

生成的源码和thrift定义的是一致的,那么实现接口,启动client和server端即可。如下:

 public interface Iface {public int addStore(addStoreReq req) throws org.apache.thrift.TException;public int deleteStore(deleteStoreReq req) throws org.apache.thrift.TException;public int updateStore(updateStoreReq req) throws org.apache.thrift.TException;public java.util.List<getStoreReq> getStore(int id, java.lang.String uuid) throws org.apache.thrift.TException;}

上述是服务端源码,首先要继承改接口,然后在实现接口方法:

package org.example.demo_test;import org.apache.thrift.TException;
import org.example.demo.model.addStoreReq;
import org.example.demo.model.deleteStoreReq;
import org.example.demo.model.getStoreReq;
import org.example.demo.model.updateStoreReq;
import org.example.demo.storeInterface;import java.util.List;public class serverImpl implements storeInterface.Iface {@Overridepublic int addStore(addStoreReq req) throws TException {System.out.println("you add a store data");return 0;}@Overridepublic int deleteStore(deleteStoreReq req) throws TException {System.out.println("you delete a store data");return 0;}@Overridepublic int updateStore(updateStoreReq req) throws TException {System.out.println("you update a store data");return 0;}@Overridepublic List<getStoreReq> getStore(int id, String uuid) throws TException {System.out.println("show store lists");return null;}
}

方法已经实现接下来就是会数据传输了,原理可以看https://www.cnblogs.com/jpfss/p/10881220.html

thrift实现rpc大致分为三个过程,首先业务层代码的数据映射到idl的定义的同名接口中(内存复用);然后对映射过来的数据序列化操作,序列化协议是TProtocol ;最后实现数据流的传输,协议是TTransport

在这里插入图片描述

还有一点需要明白的是rpc传输和http传输过程类似,都是需要一个持续的非阻塞进程来响应客户端请求。

参考感谢作者!

服务端与客户端代码代码如下:

  • server
package org.example.demo_test;import org.apache.thrift.TProcessorFactory;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.TSaslNonblockingServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TServerSocket;import org.apache.thrift.transport.TTransportException;
import org.apache.thrift.transport.layered.TFramedTransport;
import org.example.demo.storeInterface;public class server {public static void main(String[] args) throws TTransportException {//设置服务器端口  TNonblockingServerSocket-非堵塞服务模型TNonblockingServerSocket serverSocket = new TNonblockingServerSocket(8899);//参数设置THsHaServer.Args arg = new THsHaServer.Args(serverSocket).minWorkerThreads(2).maxWorkerThreads(4);//处理器storeInterface.Processor<storeInterfaceImpl> processor = new storeInterface.Processor<>(new storeInterfaceImpl());arg.protocolFactory(new TCompactProtocol.Factory());arg.transportFactory(new TFramedTransport.Factory());arg.processorFactory(new TProcessorFactory(processor));TServer server = new THsHaServer(arg);System.out.println("Thrift 服务端启动成功");server.serve();}
}
  • client
package org.example.demo_test;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import org.apache.thrift.transport.layered.TFramedTransport;
import org.example.demo.model.addStoreReq;
import org.example.demo.model.deleteStoreReq;
import org.example.demo.model.getStoreReq;
import org.example.demo.storeInterface;import java.util.List;public class client {public static void main(String[] args) throws TException {TTransport transport = new TFramedTransport(new TSocket("localhost", 9000), 600);TProtocol protocol = new TCompactProtocol(transport);storeInterface.Client client = new storeInterface.Client(protocol);deleteStoreReq deleteStoreReq = new deleteStoreReq(1);transport.open();// 接口方法client.deleteStore(deleteStoreReq);List<getStoreReq> store = client.getStore(1, "333");System.out.println(store);return ;}
}

demo地址:https://gitee.com/fireapproval/daxu/tree/master/thrift-demo

Go实现

thrift文件和上述一直,生成Go源码:thrift -r -gen go demo.thrift。若对命令不熟悉通过thrift -help查看 。

  1. 初始目录(仅包含thrift文件)

在这里插入图片描述
再次之前首先要确保安装了thrift插件,thrift -version

在这里插入图片描述
若未安装可参考如下步骤:

  1. 下载thrifthttps://archive.apache.org/dist/thrift/
  2. 系统高级设置配置环境变量(Linux修改配置文件即可)

thrift -r -out ./ --gen go demo.thrift

在这里插入图片描述
该命令生成了构建rpc的全部源码,如demo文件夹

在这里插入图片描述
该文件夹是thrift一键生成的,文件名取决于namespace的命名。

==注意在生成的代码中可能会报错,注意观察如果是引入报包是正常的,因为生成的代码是将其本身的目录作为根目录,而实际上应该以项目目录为根目录,修改一下即可。另外要是生成的代码报错,确定引入包了情况下可能是thrift和go版本差太多了,相应减低版本即可。

在这里插入图片描述
如果在自动生成的代码中某些方法爆红就是版本问题了,在如下的网站找到相近的版本就行了

在这里插入图片描述

在生成的代码中,XXX_XXX-remote是测试代码无关核心功能,xxx_xxx是根据接口IDL的接口命名的。其中核心文件是和namespace命名一样的文件。

在上述的核心文件中存在在thrift文件名称完全一样的接口,该接口就是rpc服务端接口,按照thrift的rpc传输原理,Processer、Protocal、Transport分阶段完成。

在这里插入图片描述

还要实现对服务端接口的重写,实现内存共用。

服务端实现:

package mainimport ("context""errors""fmt""github.com/apache/thrift/lib/go/thrift""thriftdemo/demo"
)// 操作对象
type Store struct {}// 实现服务端接口
// 以下所用到的参数均在thrift生成的很小代码中获取
func (s *Store) AddStore(ctx context.Context, req *demo.AddParam) (_r int32, _err error){return 1,errors.New("add store fail")
}func (s *Store) DeleteStore(ctx context.Context, req *demo.DeleteParam) (_r int32, _err error) {return 1,errors.New("delete store fail")
}func (s *Store) UpdateStore(ctx context.Context, req *demo.UpdateParam) (_r int32, _err error)  {return 1,nil
}func (s Store) GetStore(ctx context.Context, id int32, uuid string) (_r []*demo.GetParam, _err error)  {P1 := demo.GetParam{ID: 1,StoreName: "XIAOXU",Type: 1,UUID: "33-55",IdentifyTime: "2023",CreateAt: "2023",Status: 1}list :=make([]*demo.GetParam,1)list[0]= &P1return list,nil
}//实现rpc服务端
func main(){storeTmp := Store{}// demo获取thrift传输各个阶段对象process := demo.NewStoreInterfaceProcessor(&storeTmp)socket, err := thrift.NewTServerSocket(":9000")if err  != nil{panic(err)}factory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory())factoryDefault := thrift.NewTBinaryProtocolFactoryDefault()server := thrift.NewTSimpleServer4(process, socket, factory, factoryDefault)fmt.Println("rpc服务端启动端口为9000")server.Serve()
}

方法的实现类也可以拆分,这里都写在main函数了。

客户端实现:

package mainimport ("context""fmt""github.com/apache/thrift/lib/go/thrift""log""thriftdemo/demo"
)func main()  {conf := &thrift.TConfiguration{}transport := thrift.NewTSocketConf("localhost:9000", conf)// 创建客户端协议confN := &thrift.TConfiguration{}protocolFactory := thrift.NewTBinaryProtocolFactoryConf(confN)client := demo.NewStoreInterfaceClientFactory(transport, protocolFactory)if err := transport.Open(); err != nil {log.Fatalln("Error opening:", "localhost" + ":9000")}defer transport.Close()//d, err := client.GetStore(context.Background(),1,"2233")//if err!=nil{////}d ,err:= client.AddStore(context.Background(),&demo.AddParam{})if err != nil{}fmt.Println(d)
}

protobuf和thrift一样都是接口定义语言,通过工具生成各个语言的源码,他们的序列化协议不一样,用法都一样。

https://github.com/protocolbuffers/protobuf

https://protobuf.dev/getting-started/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/286180.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp 预览图片

preImg(index){let urls []this.images.map((item,i) > {if(indexi){urls.unshift(item.file_path)}else{urls.push(item.file_path)}})uni.previewImage({urls})}

第三周:Python能力复盘

资料&#xff1a; 《笨办法学Python》阅读地址&#xff1a;https://www.bookstack.cn/read/LearnPython3TheHardWay 《廖雪峰Python教程》阅读地址&#xff1a;http://t.cn/RK0qGu7 《机器学习numpy与pandas基础》&#xff1a;https://zhuanlan.zhihu.com/p/639733816 《matplo…

k8s链接数据库故障Waiting for table metadata lock

场景&#xff1a;早上来发现一个程序&#xff0c;链接mysql数据库有点问题&#xff0c;随后排查&#xff0c;因为容器在k8s里面。所以尝试重启了pod没有效果 一、重启pod: 这里是几种在Kubernetes中重启Pod的方法: 删除Pod,利用Deployment重建 kubectl delete pod mypodDepl…

运维知识点-Kubernetes_K8s

Kubernetes RBAC配置不当攻击场景攻击过程 RBAC配置不当 Service Account本质是服务账号&#xff0c;是Pod连接K8s集群的凭证。 在默认情况下&#xff0c;系统会为创建的Pod提供一个默认的Service Account&#xff0c; 用户也可以自定义Service Account&#xff0c;与Service…

利用夜莺开源版对H3C无线设备监控

编者荐语&#xff1a; 真正搞监控的人肯定知道 SNMP 水有多深&#xff0c;有时我甚至腹黑猜测&#xff0c;这些厂商是故意的吧&#xff0c;&#xff0c;&#xff0c;指标不标准&#xff0c;格式各异&#xff0c;只能靠一款灵活的采集器了&#xff0c;本文是夜莺社区用户写的文章…

数据结构:图解手撕B-树

文章目录 为什么需要引入B-树&#xff1f;B树是什么&#xff1f;B树的插入分析 本篇总结的内容是B-树 为什么需要引入B-树&#xff1f; 回忆一下前面的搜索结构&#xff0c;有哈希&#xff0c;红黑树&#xff0c;二分…等很多的搜索结构&#xff0c;而实际上这样的结构对于数…

竞赛保研 YOLOv7 目标检测网络解读

文章目录 0 前言1 yolov7的整体结构2 关键点 - backbone关键点 - head3 训练4 使用效果5 最后 0 前言 世界变化太快&#xff0c;YOLOv6还没用熟YOLOv7就来了&#xff0c;如果有同学的毕设项目想用上最新的技术&#xff0c;不妨看看学长的这篇文章&#xff0c;学长带大家简单的…

SpringBoot接入轻量级分布式日志框架GrayLog

1.前言 日志在我们日常开发定位错误&#xff0c;链路错误排查时必不可少&#xff0c;如果我们只有一个服务&#xff0c;我们可以只简单的通过打印的日志文件进行排查定位就可以&#xff0c;但是在分布式服务环境下&#xff0c;多个环境的日志统一收集、展示则成为一个问题。目…

掌握这个技巧,你也能成为学习高手!

在当今社会&#xff0c;思想政治学习具有重要的意义。随着社会的不断发展&#xff0c;个体与集体之间的关系、公共事务的处理、社会责任感等问题愈发凸显。 思政通学习小程序作为一种现代化的学习手段&#xff0c;为我们提供了更便捷、高效的途径&#xff0c;使我们更好地理解和…

实战 | API接口泄露=>未授权访问=>垂直越权=>信息泄露

文章目录 实战 | API接口泄露>未授权访问>信息泄露0x01 前言0x02 初探系统0x03 API接口泄露0x04 未授权访问系统日志接口0x05 垂直越权0x06 信息泄露 实战 | API接口泄露>未授权访问>信息泄露 0x01 前言 免责声明&#xff1a;请勿利用文章内的相关技术从事非法测…

TensorRT 深入介绍

前言 一、tensorRT 做了那些优化 1、算子融合 常见的算子融合有以下操作&#xff1a; conv bn reluconv reluconv relu max_poolconv add reluconv add 2、量化 因为我们在训练的时候&#xff0c;参数的每次更新的幅度都是十分微小的。所以为了保证在训练时梯度反…

rabbitmq界面主要参数分析

本篇主要分析rabbitmq broker界面参数 rabbitmq界面主要参数分析 1、connections User Name: user - 连接所使用的用户名。 State: running - 连接当前的状态&#xff0c;这里表明连接是活动的。 SSL/TLS: ○ - 表示这个连接没有使用SSL/TLS加密。 内部或受信任的网络中可能…