`
zijan
  • 浏览: 64662 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

Tatala 中文教程

阅读更多

Tatala 中文教程

 

概述

Tatala是一个简单易用的RPC中间件,并且跨语言跨平台。它将调用方法转变成字节数组(包括被调用类名,目标方法名,参数序列和返回值),在socket基础上实现客户端和服务器之间的互相通信。

目前,Tatala支持Java的客户端与服务器端,和C#的客户端。

特性

  • 简单易用可以快速开发和建立网络组件
  • 跨语言跨平台
  • 高性能和分布式
  • 传输协议为短小精悍的二进制
  • 支持socket长连接
  • 客户端与服务器端多线程处理
  • 支持异步请求
  • 对于大数据支持压缩传输
  • 支持服务器端主动推送消息
  • 客户端程序可以捕获服务端抛出的异常,使客户端支持事务回滚
  • 支持Google Protocol Buffers作为对象序列化进行网络传输
  • 支持在服务端注册多个filter,在调用业务代码之前预处理传入的数据,注入业务逻辑,如权限检查等
  • 能够用于跨语言的远程方法调用RPC,高性能的缓存服务器,分布式的消息服务,多人在线游戏服务器,等等

快速开始

下载tatala.jar 包含在你项目的classpath中。

简单编程是Tatala第一考虑因素,所以用它建立RPC的方式,让开发者感觉就像调用本地普通方法一样简单。不用考虑网络,线程这些东西。

现在举一个例子,假如我们有个服务器端的服务ExampleManager接口 和 ExampleManagerImpl实现类。

ExampleManager.java

public interface ExampleManager{
    public String sayHello(int Id, String name);
}

ExampleManagerImpl.java

public class ExampleManagerImpl implements ExampleManager{
    public String sayHello(int Id, String name) {
        return "["+Id+"]"+"Hello "+name+" !";
    }
}

我们还需要在服务端建立一个socket服务类来部署我们的业务逻辑,在这个例子中socket服务监听端口是10001。 ExampleServer.java

public class ExampleServer {
    public static void main(String args[]) {
        int listenPort = 10001;
        int poolSize = 10;
        AioSocketServer server = new AioSocketServer(listenPort, poolSize);
        server.start();
    }
}

然后客户端的代码类似这样:

EasyClient.java

public class EasyClient {
    private static TransferObjectFactory transferObjectFactory;
    private static ExampleManager manager;

    public static void main(String[] args) {
        transferObjectFactory = new TransferObjectFactory("127.0.0.1", 10001, 5000);
        transferObjectFactory.setImplClass("ExampleManagerImpl");
        manager = (ExampleManager)ClientProxyFactory.create(ExampleManager.class, transferObjectFactory);

        String result = manager.sayHello(18, "JimT");
        System.out.println("result: "+result);
    }
}

创建一个TransferObjectFactory对象,设置server端的IP地址,端口号和超时时间。设置被调用的实现类的类名,建立proxy,调用方法。当然我们需要把接口类(ExampleManager.class) 加入到客户端的classpath里。这就是建立一个Tatala RPC的所有代码,不需要任何配置文件,是不是很简单?

更多例子请看教程。

教程

一般开发步骤

对于建立一个Tatala RPC,大致需要三个步骤:

  • 建立服务端业务逻辑和socket服务类

  • 建立Tatala代理类, 它是介于客户与服务器端之间的中介类。

  • 客户端代码

建立服务器端业务逻辑,包括接口(非必须)和实现类。

public interface ExampleManager {
    public String sayHello(int Id, String name);
}
public class ExampleManagerImpl implements ExampleManager{
    public String sayHello(int Id, String name) {
        return "["+Id+"]"+"Hello "+name+" !";
    }
}

建立socket 服务类,用于部署业务逻辑。

public class ExampleServer {
    public static void main(String args[]) {
        int listenPort = 10001;
        int poolSize = 10;
        AioSocketServer server = new AioSocketServer(listenPort, poolSize);
        server.start();
    }
}

建立客户端Proxy。

public class ExampleClientProxy {
    public String sayHello(int Id, String name) {
        TransferObjectFactory transferObjectFactory = new TransferObjectFactory("127.0.0.1", 10001, 5000);
        TransferObject to = transferObjectFactory.createTransferObject();
        to.setCalleeClass("com.qileyuan.tatala.example.proxy.ExampleServerProxy");
        to.setCalleeMethod("sayHello");
        to.registerReturnType(TransferObject.DATATYPE_STRING);
        to.putInt(Id);
        to.putString(name);
        Object resultObj = ServerExecutor.execute(to);
        String result = (String) resultObj;
        return result;
    }
}

创建一个TransferObjectFactory对象,设置server端的IP地址,端口号和超时时间。由TransferObjectFactory创建一个transfer object,设置被调用的类名(这里是server proxy),目标方法和返回类型。向transfer object顺序放入参数值。最后调用ServerExecutor。

建立服务器端Proxy。

public class ExampleServerProxy {
    private ExampleManager manager = new ExampleManagerImpl();
    public String sayHello(TransferObject to) {
        int Id = to.getInt();
        String name = to.getString();
        String result = manager.sayHello(Id, name);
        return result;
    }
}

在服务器端建立接收类和方法。从transfer object中得到参数值(注意顺序要和客户端放入参数的顺序一致),再调用真正的业务逻辑。

最后建立客户端代码,向Client Proxy发出调用并得到返回结果。

public class ExampleClient {
    public static void main(String[] args) throws Exception {
        ExampleClientProxy proxy= new ExampleClientProxy();
        String result = proxy.sayHello(18, "JimT");
    }
}

序列化类型

可以使用序列化的对象作为参数。

to.putSerializable("account", account);

自定义类型参数Wrapper Class

出于性能考虑,可以用wrapper类代替序列化对象。Wrapper类是用户自定义类,手动转化各种属性类型。

AccountWrapper accountWrapper = new AccountWrapper(account);
to.putWrapper("account", accountWrapper);

AccountWrapper 类包含了 Account

public class AccountWrapper implements TransferObjectWrapper {
    private Account account;
    public AccountWrapper(Account account) {
        this.account = account;
    }
    public int getLength(){
        return TransferUtil.getLengthOfInt() + 
               TransferUtil.getLengthOfString(account.getName()) +
               TransferUtil.getLengthOfString(account.getAddress());
    }
    public void getByteArray(TransferOutputStream touts) {
        touts.writeInt(account.getId());
        touts.writeString(account.getName());
        touts.writeString(account.getAddress());
    }
    public TestAccountWrapper getObjectWrapper(TransferInputStream tins){
        account = new TestAccount();
        account.setId(tins.readInt());
        account.setName(tins.readString());
        account.setAddress(tins.readString());
        return this;
    }
}

有三个实现方法:
getLength - get customization object byte array length
getByteArray - convert customization object into byte array
getObjectWrapper - convert byte array back to customization object

异步

在客户端Proxy,Tatala支持异步调用。

to.setAsynchronous(true);
Future<AccountWrapper> future = (Future<AccountWrapper>) ServerExecutor.execute(to);
accountWrapper = future.get();

压缩传输

Tatala支持压缩传输数据。不管向服务器传输大数据还是要从服务器得到大数据,都可以在client proxy设置压缩标志。

to.setCompress(true);

非反射调用Default Server Proxy

在服务器端执行被调用类是通过反射来完成的,如果不希望用反射,可以让server Proxy继承DefaultProxy 并且注册到socket server中。而在client Proxy 不需要设置任何被调用类名。

把default proxy注册到socket server中。

DefaultProxy defaultProxy = new ExampleDefaultProxy();
server.registerProxy(defaultProxy);
server.start();

建立自己的Default Proxy ExampleDefaultProxy.java

public class ExampleDefaultProxy extends DefaultProxy{
    private ExampleManager manager = new ExampleManagerImpl();
    public Object execute(TransferObject to){
        String calleeMethod = to.getCalleeMethod();
        if(calleeMethod.equals("sayHello")){
            int Id = to.getInt();
            String name = to.getString();
            String result = manager.sayHello(Id, name);
            return result;
        }
        return null;
    }
}

无Proxy调用

如果你觉得写Proxy很烦,那你可以试试创建无Proxy的调用方式。这种方式让你不需要编写任何client 和 server proxy代码。因为它是基于Java动态代理技术的,所以性能会有一点点影响,并且不支持wrapper类和C#的版本。

在前面,“快速开始”里第一个例子EasyClient就是无Proxy调用。

服务端推送

对于长连接,有时需要服务端主动推送消息给客户端,例如在聊天室中广播聊天内容给所有用户。只要我们在建立长连接后,保持client session,就可以在业务逻辑中,通过session直接发送消息或方法调用到客户端。有了这个功能可以用Tatala建立简单易用的网络游戏服务器。

详细的例子看聊天室的演示代码。(tatala-java-example里的chatroom)

传输截获与注入Session Filter

Tatala支持在服务器端在调用业务代码之前,截获每次数据传输,预处理传入的二进制字节流或者注入业务逻辑,比如访问权限检查等。

建立session filter

public class MyFilter implements SessionFilter {
    public void onClose(ServerSession session) {
        //on connection close, do something
    }
    public boolean onReceive(ServerSession session, byte[] receiveData) {
        //after each receive, do something
        return true;
    }
}

把新建的filter注册到socket server中。

AioSocketServer server = new AioSocketServer(listenPort, poolSize);
MyFilter filter = new MyFilter();
server.registerSessionFilter(filter);

捕获服务端抛出的异常

在某些情况,客户端需要捕获服务端抛出的异常,使得客户端可以事务回滚。 创建ExampleReturnException继承TatalaRollbackException

public class ExampleReturnException extends TatalaRollbackException{
    private static final long serialVersionUID = 1L;
    public ExampleReturnException() {
        super();
    }
    public ExampleReturnException(String msg) {
        super(msg);
    }
}

在ExampleManagerImpl中创建一个需要被客户端捕获异常的方法。

    public void exceptionCall(int Id) {
        if(Id < 0){
            throw new ExampleReturnException("Server error: id < 0");
        }
    }

ExampleServerProxy

    public void exceptionCall(TransferObject to) {
        int Id = to.getInt();
        manager.exceptionCall(Id);
    }

Client

    public void returnExceptionTest() {
        TransferObject to = transferObjectFactory.createTransferObject();
        to.setCalleeClass("com.qileyuan.tatala.example.proxy.ExampleServerProxy");
        to.setCalleeMethod("exceptionCall");
        to.putInt(-1);
        to.registerReturnType(TransferObject.DATATYPE_VOID);
        ServerExecutor.execute(to);
    }

因为TatalaRollbackException继承自RuntimeException,所以在代码中是否需要try-catch是可选项,让代码更简单。

Google Protocol Buffer

既然Tatala支持二进制数组作为参数传输,我们就可用Protobuf作为对象序列化解决方案,代替Serializable和WrapperClass。

Client Proxy

    public Account getAccountProto (Account account) throws InvalidProtocolBufferException{
        TransferObject to = transferObjectFactory.createTransferObject();
        to.setCalleeClass("com.qileyuan.tatala.example.proxy.ExampleServerProxy");
        to.setCalleeMethod("getAccountProto");
        to.registerReturnType(TransferObject.DATATYPE_BYTEARRAY);

        AccountProto.Account.Builder accountProtoBuilder = AccountProto.Account.newBuilder();
        accountProtoBuilder.setId(account.getId());
        accountProtoBuilder.setName(account.getName());
        to.putByteArray(accountProtoBuilder.build().toByteArray());

        byte[] returnByteArray = (byte[]) ServerExecutor.execute(to);

        AccountProto.Account accountProto = AccountProto.Account.parseFrom(returnByteArray);
        if(accountProto != null){
            Account returnAccount = new Account();
            returnAccount.setId(accountProto.getId());
            returnAccount.setName(accountProto.getName());
            returnAccount.setAddress(accountProto.getAddress());
            return returnAccount;
        }else{
            return null;
        }
    }

Server Proxy

    public byte[] getAccountProto(TransferObject to) throws InvalidProtocolBufferException {
        byte[] byteArray = to.getByteArray();
        AccountProto.Account accountProto = AccountProto.Account.parseFrom(byteArray);
        Account account = new Account();
        account.setId(accountProto.getId());
        account.setName(accountProto.getName());
        account.setAddress(accountProto.getAddress());

        Account returnAccount = manager.getAccount(account);

        AccountProto.Account.Builder accountProtoBuilder = AccountProto.Account.newBuilder();
        accountProtoBuilder.setId(returnAccount.getId());
        accountProtoBuilder.setName(returnAccount.getName());
        accountProtoBuilder.setAddress(returnAccount.getAddress());

        return accountProtoBuilder.build().toByteArray();
    }

传输协议

在客户端把调用的方法信息设置到transfer object里, Tatala把transfer object转换成字节数组并且发送给服务器。在服务器端把接收到的字节数组再还原成包含调用信息的transfer object。包括被调用类名,目标方法名,参数值和返回类型等。Tatala 执行器获得调用信息执行目标方法。

支持类型

Tatala支持的参数和返回类型表格

Type Java C#
bool Y Y
byte Y Y
short Y Y
chat Y Y
int Y Y
long Y Y
float Y Y
double Y Y
Date Y Y
String Y Y
byte[] Y Y
int[] Y Y
long[] Y Y
float[] Y Y
double[] Y Y
String[] Y Y
Serializable Y N
Protobuf Y Y
WrapperClass Y Y

其它描述

需要JDK1.7,因为使用了Java AIO。

第三方类库包括Protobuf,Log4j。

License

Apache License Version 2.0

分享到:
评论

相关推荐

    【图像压缩】 GUI矩阵的奇异值分解SVD灰色图像压缩【含Matlab源码 4359期】.zip

    Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    node-v0.9.2-x86.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    【尺寸检测】机器视觉图像目标尺寸测量【含Matlab源码 4087期】.zip

    Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【图像加密】双随机相位图像加密解密【含Matlab源码 4118期】.zip

    Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    金融支付:浅析如何用定期资产设计活期产品.docx

    金融支付:浅析如何用定期资产设计活期产品.docx

    Excel模板个人简历文艺清新单页06.docx

    Excel模板个人简历文艺清新单页06.docx

    【图像重建】 POCS算法超分辨率图像重建(含PSNR)【含Matlab源码 4404期】.zip

    Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    吹瓶转线清线(清场)记录表.xls

    吹瓶转线清线(清场)记录表.xls

    odis14.1安装包(专检5054B专用含驱动)

    支持win10,win11(21H2及以前版本)系统

    Modbus Slave version 9.3.2 Build 2156

    Modbus Slave version 9.3.2 Build 2156, modbus 协议从机,非常好用,包括32位与64位

    Excel模板个人简历稳重大气单页03.docx

    Excel模板个人简历稳重大气单页03.docx

    11记录控制程序.doc

    11记录控制程序.doc

    【图像边缘检测】自适应阈值的八方向和四方向sobel图像边缘检测【含Matlab源码 2058期】.zip

    Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    第一步安装.zip

    第一步安装.zip

    node-v0.9.0-x64.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    【图像融合】红外与可见光图像融合与配准【含Matlab源码 4214期】.zip

    Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    【图像去噪】 GUI中值+均值+维纳+小波滤波图像去噪(含PSNR)【含Matlab源码 753期】.zip

    Matlab领域上传的视频均有对应的完整代码,皆可运行,亲测可用,适合小白; 1、代码压缩包内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主或扫描视频QQ名片; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    C风险心理承受能力测试20210603.docx

    C风险心理承受能力测试20210603.docx

    HPLC实验报告.docx

    HPLC实验报告.docx

    Screenshot_20240517_181056.jpg

    Screenshot_20240517_181056.jpg

Global site tag (gtag.js) - Google Analytics