I.背景

众所周知,Thrift是一个RPC的框架,其可用于不同语言之间的服务相互调用。比如最近接触到的一个运用环境:

*前端使用Node.Js重构了部分我们的老旧代码(前后端未分离的SpringBoot项目),我们后端使用zookeeper+Thrift为新的Node.Js前端项目提供基本的DAO层服务支持*

所以基于这个项目,我大概了解了一下Thrift,该文章则均以Java为基础语言。


II.如何入门

因为后端已经有一套服务注册和暴露机制,所以服务已经是RPC的形式,所以我们仅需要使用Thrift IDL来重写一遍我们需要暴露的方法即可,Thrift IDL有两个比较好的参考选择:

  • Thrift 类型说明可以参考官方文档: Thrift Type,简单来说,thrift基本支持所有的Java基本类型以及引用类型:bool(boolean)、byte(byte)、i16(short)、i32(int)、i64(long)、double(double)、string(String)、binary(byte[])以及一些常用容器和自建类型(Struct);
  • Thrift IDL的书写规范则可以参考Thrift: The Missing Guide,这个文档相较于官方文档有更多的例子可以参考。

III.TIPS

  • 很多参考和学习文档,都将servicesstruct放在一个.thrift文件中,这种方式将service和其所需的struct绑定在一起,会导致个别struct重复出现在多个.thrift文件中,导致大量的代码重复。所以,应该与Java的编码风格保持一致,采用POJO类(struct)+接口(services)的方案,利用include关键字,将struct引进services中使用
  • Thrift支持基本所有的Java基本类型,但是注意是基本类型,类似于Java中的Integer、Boolean、Long、Double等基本类型包装类是不支持的,或许你可以使用struct实现一个类似的包装类结构进行数据承载。
  • Thrift支持enum枚举类型,但是如果没有description的枚举类型也可以直接使用string来承接。
  • Thrift是通过序列化和反序列化来获取对应struct结构体的数据的,所以struct中的数据顺序一定要和java文件中的一致,否则可能会出现数据对应关系错乱或者数据丢失。
  • 在编写struct体时,要注意java对象父级,如果父级中含有变量,不要忘记其变量的书写,且顺序一定在前面。
  • 如非必要,java对象中的常量可以不出现在thrift idlstruct结构体中。
  • 时间Date我们固定使用timestamp时间戳的形式传递,即long型。

IV. 例子

我们现在有一个Account对象,需要将其变为thrift文件,Account的结构如下:

    public class Account extends BaseEntity implements SecurityUser{

		private static final long serialVersionUID = 1L;
public static final String PASSWORD_TIME = "passwordTime"; private String password; // 密码
private Date createTime; // 创建时间
private Date lastLoginTime; // 最后登录时间
private int loginCount = 0; // 登录次数
private boolean enabled = true;
private Date passwordTime; //密码修改时间
private boolean freeze; //账户是否被冻结 //该账户的绑定信息,非持久化字段
@Transient
private Set<Binding> bindings = new HashSet(); @Transient
private String name;//保存登录时用的用户名,非持久化字段 //省略getter和setter
}

根据上述结构我们可以书写如下的Account.thrift:

/**
* 账户信息
*/
struct Account{
1: string password, //密码
2: i64 createTime, //创建时间
3: i64 lastLoginTime, //最后登录时间
4: i32 loginCount, //登陆次数
5: bool enabled=true,
6: i64 passwordTime, //密码修改时间
7: bool freeze, //账户是否被冻结
}

但是经过测试前端调用接口获取到的Account信息,要么数据错位,要么数据丢失,问题出在哪里呢?这时,我们发现Account对象继承了BaseEntity,实现了SecurityUser,我们去查看一下继承的BaseEntity对象:

public abstract class BaseEntity extends IdEntity implements Cacheable, TypeAliases{

	private static final long serialVersionUID = 1L;

	private static final String CACHE_NAMESPACE = "entity" ;

	public BaseEntity() {
super();
} public BaseEntity(Long id) {
super(id);
} //省略下方代码
}

我们发现其中并没有非常量变量,但是BaseEntity又继承了IdEntity,所以我们得再去看一看IdEntity:

public abstract class IdEntity implements Serializable{

	private static final long serialVersionUID = -1L;

	/**
* Hibernate JPA环境中使用@GenericGenerator注解生成主键
*/
@Id
@GeneratedValue(generator = "longIdGenerator")
@GenericGenerator(name = "longIdGenerator", strategy = "net.rekent.framework.id.LongIdGenerator")
protected Long id; public IdEntity() {
super();
} public IdEntity(Long id) {
super();
this.id = id;
} //省略getter和setter
}

这时我们发现IdEntity中含有一个Id的变量,所以我们需要重构一下刚刚书写的Account.thrift

/**
* 账户信息
*/
struct Account{
1: i64 id, //账户Id
2: string password, //密码
3: i64 createTime, //创建时间
4: i64 lastLoginTime, //最后登录时间
5: i32 loginCount, //登陆次数
6: bool enabled,
7: i64 passwordTime, //密码修改时间
8: bool freeze, //账户是否被冻结
}

书写完Account.thrift后,我们需要写其相应的接口即service,查看Interface AccountService:

public interface AccountService {

	/**
* 创建账户
* @param account
* @return 返回创建后的Account对象
*/
Account create(Account account); /**
* 更新账户信息
* @param account
* @return
*/
boolean update(Account account); /**
* 修改开放平台密码 传入的 密码是未加密的
* @param username
* @param newPassword
* @return
*/
boolean updatePasswd(String username, String newPassword); /**
* 重置密码
* @param username 用户名
* @param newPassword 新密码
*/
void resetPasswd(String username, String newPassword); /**
* 验证用户名和密码是否匹配
* @param username
* @param password
*/
boolean matches(String username,String password);
}

有很多方法,但是如果前端只需要用到校验用户名和密码的方法,那么我就只需要暴露创建账户的方法,即:

include "Account.thrift"

service AccountService{
/*
* 校验用户名和密码
*/
bool matches(1: string username,2: string password),
}

这样我们就完成了一个关于用户名和密码的校验方法的thrift idl文档的书写,前端需要执行thrift的一条语句对文件进行编译,以node.js为例(具体可参考:Apache Thrift Tutorial

thrift --gen <language> <Thrift filename>

thrift -r --gen js:node Account.thrift
thrift -r --gen js:node AccountService.thrift

Thrift IDL使用方式的更多相关文章

  1. Thrift IDL

    Thrift类型 Thrift类型系统旨在允许程序员尽可能使用本机类型,无论使用何种编程语言.此信息基于并取代Thrift白皮书中的信息.Thrift IDL为每一种目标语言提供了用于生成代码的类型描 ...

  2. 环境初始化 Build and Install the Apache Thrift IDL Compiler Install the Platform Development Tools

    Apache Thrift - Centos 6.5 Install http://thrift.apache.org/docs/install/centos Building Apache Thri ...

  3. Thrift IDL基本语法

    简言:介绍Thrift的IDL基本语法,初次使用或多或少的会有很有"坑"要踩,但是我们要遇山挖山,遇海填海,在学习的道路上坚定的走下去,方可日后吹牛B! IDL Thrift 采用 ...

  4. WeText项目:一个基于.NET实现的DDD、CQRS与微服务架构的演示案例

    最近出于工作需要,了解了一下微服务架构(Microservice Architecture,MSA).我经过两周业余时间的努力,凭着自己对微服务架构的理解,从无到有,基于.NET打造了一个演示微服务架 ...

  5. NET实现的DDD、CQRS与微服务架构

    WeText项目:一个基于.NET实现的DDD.CQRS与微服务架构的演示案例 最近出于工作需要,了解了一下微服务架构(Microservice Architecture,MSA).我经过两周业余时间 ...

  6. Hive之 hive的三种使用方式(CLI、HWI、Thrift)

    Hive有三种使用方式——CLI命令行,HWI(hie web interface)浏览器 以及 Thrift客户端连接方式. 1.hive  命令行模式 直接输入/hive/bin/hive的执行程 ...

  7. Thrift:Quick Start

    Thrift 快速开始 1 Thrift 介绍 目前流行的服务调用方式有很多种,例如基于 SOAP 消息格式的 Web Service,基于 JSON 消息格式的 RESTful 服务等.其中所用到的 ...

  8. Apache Avro 与 Thrift 比较

    http://www.tbdata.org/archives/1307 Avro和Thrift都是跨语言,基于二进制的高性能的通讯中间件. 它们都提供了数据序列化的功能和RPC服务. 总体功能上类似, ...

  9. [转] thrift的使用介绍

    http://gemantic.iteye.com/blog/1199214 一.About  thrift   二.什么是thrift,怎么工作? 三.Thrift  IDL 四.Thrift   ...

随机推荐

  1. Spring Cloud 微服务入门(二)--Spring Cloud 架构

    Spring Cloud整体核心架构:Rest服务,在Spring Cloud配置过程中,都是遵循Rest风格规范,在Rest处理中,必不可少两个对象端:服务的提供者(provider)和服务消费者( ...

  2. angular.js-1初识

    初识AngularJS AngularJS 为了克服HTML在构建页面上的不足,通过新的属性和表达式扩展了 HTML(AngularJS 通过指令扩展了 HTML,且通过表达式绑定数据到 HTML). ...

  3. 本人擅长Ai、Fw、Fl、Br、Ae、Pr、Id、Ps等

    本人擅长Ai.Fw.Fl.Br.Ae.Pr.Id.Ps等软件的安装与卸载,精通CSS.JavaScript.PHP.ASP.C.C++.C#.Java.Ruby.Perl.Lisp.python.Ob ...

  4. Delphi 拦截滚轮事件不响应滚轮的上下滚动

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  5. CAT 安装运行配置教程

    CAT安装教程 首先安装mysql数据库,具体步骤参阅<mysql免安装教程>--http://www.cnblogs.com/halberts/p/8723938.html 下载CAT代 ...

  6. 基于CentOS-6.9_x64系统QT环境搭建

    想从事QT开发的人员,首先要做的第一件事就是开发环境的搭建.本人也是一位刚入门的新手,为了搭建这么一个环境,参考了很多的网上教程,然而中间依然走了不少弯路.现将过程记录下来. 一.开发环境    Ce ...

  7. django之路由分组,反向解析,有名,无名分组

    路由层 无名分组 有名分组 反向解析 路由分发 名称空间 伪静态的概念 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'test',vi ...

  8. sublime解决gbk中文乱码包括Package Control: Install Package 无法使用

    最近喜欢上了sublime,打算抛弃notepad,但是发现sublime居然不支持gbk编码,再上网查找资料之后,总结了一套解决方法,目前为止是行之有效的. 日期:2019年3月14日 第一步:到G ...

  9. 北京Uber优步司机奖励政策(12月13日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  10. day 2 给程序传递参数

    1.如何实现变化name name = "alex" print("欢迎%s前来指导学习"%name) 欢迎alex前来指导学习 2.sys.argv impo ...