接口定义语言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 demo

struct addStore{
    1:i32 id
    2:string storeName
    3:i32 type
    4:string uuid
    5:string identitionTime
    6:string createAt
    7:i32 status
}


struct delete{
    1:i32 id
}

struct update{
    1:i32 id
    2:string storeName
    3:i32 type
    4:string uuid
    5:string identitionTime
    6:string createAt
    7:i32 status
}

struct getStore{
    1:i32 id
    2:string storeName
    3:i32 type
    4:string uuid
    5:string identitionTime
    6:string createAt
    7: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 {
    @Override
    public int addStore(addStoreReq req) throws TException {
        System.out.println("you add a store data");
        return 0;
    }

    @Override
    public int deleteStore(deleteStoreReq req) throws TException {
        System.out.println("you delete a store data");
        return 0;
    }

    @Override
    public int updateStore(updateStoreReq req) throws TException {
        System.out.println("you update a store data");
        return 0;
    }

    @Override
    public 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 main

import (
	"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]= &P1
	return 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 main

import (
	"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/

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

BearPi Std 板从入门到放弃 - 先天神魂篇(9)(RT-Thread DAC->ADC)

简介 RT-Thread DAC->ADC 使用, 就是DAC1输出模拟量, ADC1 读取模拟量转化成电压值, 基于开发板 &#xff1a; Bearpi Std(小熊派标准板)主芯片: STM32L431RCT6串口: Usart1DAC1: PA5, OUT2ADC1: PC2, IN3将板子上的E53 接口, 5 和 6用排线相连, 即实现内部DAC1->ADC1 …

C语言入门(字符串正反连接(fgets()、gets()用法))

目录 ​编辑 题目描述 输入格式 输出格式 样例输入 样例输出 解题思路 题目描述 所给字符串正序和反序连接&#xff0c;形成新串并输出 输入格式 任意字符串&#xff08;长度<50&#xff09; 输出格式 字符串正序和反序连接所成的新字符串 样例输入 123abc 样例输出 12…

【VScode】设置语言为中文

1、下载安装好vscode 2、此时可看到页面为英文&#xff0c;为方便使用可切换为中文 3、键盘按下 ctrlshiftP 4、在输入框内输入configure display language 5、选择中文&#xff0c;restart即可&#xff08;首次会有install安装过程&#xff0c;等待安装成功后重启即可&am…

【玩转Node.JS】=> 之 Buffer(缓冲器)

Node.js 是一个开源、跨平台的 JavaScript 运行时环境 文章目录 Buffer 概念Buffer 的特点创建 BufferBuffer 与字符串的转化 Buffer 的读写 Buffer 概念 Buffer 是一个类似于数组的 对象 &#xff0c;用于表示固定长度的字节序列Buffer 本质是一段内存空间&#xff0c;专门用…

2018年第七届数学建模国际赛小美赛A题空中加油飞行计划解题全过程文档及程序

2018年第七届数学建模国际赛小美赛 A题 空中加油飞行计划 原题再现&#xff1a; 太平洋中部一个小岛上的居民被自然灾害困住。救援人员需要派遣一架轻型飞机运送少量急救药品到岛上&#xff0c;并运送一名重伤者到医疗基地求救。岛上有一个无人值守的简易机场&#xff0c;可以…

css+html横向滚动+固定宽

没什么好说的&#xff0c;快上代码&#xff01; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Do…

2023.12.16 帆软report 官方模板表练习,pymysql

import pymysql# 建立与数据库的连接 conn1 pymysql.connect(host192.168.88.100,port3306,userroot,password123456,dbshopnc_db ) conn2 pymysql.connect(host192.168.88.100,port3306,userroot,password123456,dbbi_db ) # 2.创建游标对象 c1 conn1.cursor() # 3.编写sql…

OpenSSL 3.2.0新增Argon2支持——防GPU暴力攻击

1. 引言 OpenSSL新发布的3.20版本中&#xff0c;引入了一些新特性&#xff0c;包括&#xff1a; post-quantum方法Brainpool曲线QUICArgon2&#xff1a;Argon2 是一种慢哈希函数&#xff0c;在 2015 年获得 Password Hashing Competition 冠军&#xff0c;利用大量内存计算抵…

【面试】Java最新面试题资深开发-微服务篇(1)

问题九&#xff1a;微服务 什么是微服务架构&#xff1f;它与单体架构相比有哪些优势和劣势&#xff1f;解释一下服务发现和服务注册是什么&#xff0c;它们在微服务中的作用是什么&#xff1f;什么是API网关&#xff08;API Gateway&#xff09;&#xff1f;在微服务中它有何…

[学习笔记]批量迁移数据库文件

拷贝数据库文件 首先在本地运行如下SQL语句&#xff0c;查看数据库文件的磁盘位置 SELECT name, physical_name AS CurrentLocation, state_desc FROM sys.master_files默认是保存在C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA目录下 首先复制数据…

mybatis.interceptor.exception.SqLValidateException:Ilegal SQL::......

现象&#xff1a;⬇️ 描述&#xff1a;执行 SQL 没问题&#xff0c;应用代码报错 ⬇️ .mybatis.interceptor.exception.SqLValidateException&#xff1a;Ilegal SQL::SELECT voucherNo FROM voucher ORDER BY CAST(SUBSTRING(voucherNo FROM LOCATE(_, voucherNo) 1) AS U…

C语言KR圣经笔记 4.4作用域规则 4.5头文件 4.6静态变量

4.4 作用域规则 构成一个 C 程序的函数以及外部变量&#xff0c;不需要全都同时编译&#xff1b;程序的源代码可以放在多个源文件中&#xff0c;并且之前编译好的例程可以从库里面加载。需要关心的问题有&#xff1a; 要怎么写声明&#xff0c;才能使变量在编译期间被正确声明…

网络编程『socket套接字 ‖ 简易UDP网络程序』

&#x1f52d;个人主页&#xff1a; 北 海 &#x1f6dc;所属专栏&#xff1a; Linux学习之旅、神奇的网络世界 &#x1f4bb;操作环境&#xff1a; CentOS 7.6 阿里云远程服务器 文章目录 &#x1f324;️前言&#x1f326;️正文1.预备知识1.1.IP地址1.2.端口号1.3.端口号与进…

三菱plc学习入门(一,认识三菱plc)

今天就开始对三菱的plc软件入一个门&#xff0c;希望小编的文章对读者和初学者有所帮助&#xff01;欢迎评论指正&#xff0c;废话不多说&#xff0c;下面开始学习。 目录 plc的型号介绍 M表示什么&#xff1f; T表示什么&#xff1f; R表示什么&#xff1f; 为什么三菱没…

Pytorch nn.Linear()的基本用法与原理详解及全连接层简介

主要引用参考&#xff1a; https://blog.csdn.net/zhaohongfei_358/article/details/122797190 https://blog.csdn.net/weixin_43135178/article/details/118735850 nn.Linear的基本定义 nn.Linear定义一个神经网络的线性层&#xff0c;方法签名如下&#xff1a; torch.nn.Li…

得帆信息创始人-张桐,受邀出席 BV百度风投AIGC主题论坛

近日&#xff0c;得帆信息创始人兼CEO张桐&#xff0c;作为百度风投被投代表企业创始人受邀出席“向未来&#xff0c;共成长” BV百度风投AIGC主题论坛。 与包括上海市徐汇区相关部门领导、百度集团相关事业部负责人及代表&#xff0c;以及来自国寿资本、中网投、麦顿投资的投资…

install cuda cudnn tersorRT

# 安装 $ ubuntu-drivers devices$ sudo apt-get install nvidia-driver-470-server # 推荐是server&#xff0c;都可以。#delelt sudo apt --purge remove nvidia-* CUDA Toolkit Archive | NVIDIA Developerhttps://developer.nvidia.com/cuda-toolkit-archive CUDA Toolk…

【计算机网络】TCP协议——1.报文格式详解

前言 上篇讲解了UDP报文格式。TCP和UDP是同层协议&#xff0c;都属于传输层&#xff0c;数据来源于上层——应用层 目录 一. TCP协议概述 二. TCP报文格式 1. 两个问题 2. 确认号和序列号 3. 标志位字段 4. 窗口大小 5. 校验和字段 6. 紧急指针与紧急数据 7. 选项字…

后端低代码平台探索总结

业务需求快速变化的背景 我们在对业务需求进行梳理后&#xff0c;在进行程序设计时&#xff0c;对于将来可能发生变化的常量、变量、阀值、开关、条件、公式等等&#xff0c;可能会配置在环境变量或数字字典来支持可配置。但是需求变化往往会更加复杂、更加不可预测&#xff0…

PDF控件Spire.PDF for .NET【转换】演示:将多个图像转换为单个 PDF

如果您想要将多个图像合并为一个文件以便于分发或存储&#xff0c;将它们转换为单个 PDF 文档是一个很好的解决方案。这一过程不仅节省空间&#xff0c;还确保所有图像都保存在一个文件中&#xff0c;方便共享或传输。在本文中&#xff0c;您将学习如何使用Spire.PDF for .NET …