zoukankan      html  css  js  c++  java
  • erlang+thrift配合开发

    I  think, thrift is a  tcp/ip based Client-Server architecture multi-languages supported RPC framework.

    要使用thrift+erlang开发,要经过下面几个步骤。

    1.对thrift了解。

    thrift的功能的确是强劲,不过thrift缺少文档的确是它的硬伤,尤其是具体的语言的API文档更是缺少,网上基本上是java api的文档。下面是我收集的一些文档,对thrift的定义和使用都有具体的介绍,可以说是thrift的入门必备资料。

    Thrift: The Missing Guide

    有pdf文档可以下载,15页,短小精悍,我就是看了这个文档对thrift有所了解。

    thrift whitepaper

    thrift的白皮书,介绍了thrift的历史和使命。

    Apache Thrift - 可伸缩的跨语言服务开发框架

    使用java开发可以看看。

    Thrift实践

    介绍thrift的一些特性

    Apache Thrift-quick tutorial

    包括安装、使用等一系列内容。

    看完这一系列文档,对thrift的定义、使用、以及特性都会有比较深入的了解,可以减少使用中遇到的问题。

    2.thrift开发一般步骤

    Erlang中使用Thrift 里面讲到了使用erlang+thrift的一般步骤:

    第一步:编写相应的*.thrift  文件
    第二步:thrift --gen erl *.thrift,将生成的gen-erl复制到src中
    第三步:按照例子代码写一个模块,将*.thrift中的函数全都实现了,并在里面指定服务的端口号和启动thrift的框架
    第四步:将上一步写的模块添加到整个程序启动过程的最末处,启动thrift开始对外提供服务。

    3.thrift与erlang实战

    首先对thrift的erlang代码有所了解,下面这个博文就是阅读代码的心得

    Thrift Erlang实现源代码阅读

    读了这个博文后,我们就开始thrift+erlang的开发了。

    thrift+erlang的用例就有thrift源码里面的tutorial,看懂了这个示例,基本上就可以使用thrift开发erlang服务器程序。

    在这里,我使用的是另外一个示例,是在网上另外一个例子:

    初试thrift (自备梯子)

    thrift粘合erlang (自备梯子)

    定义hello.thrift文件:

    service Hello{
        string say(1:string name)
    }

    生成erl文件:

    thrift --gen erl hello.thrift

    gen-erl目录里面就有我们需要的erlang代码。

    #ls gen-erl/
    hello_constants.hrl  hello_thrift.erl  hello_thrift.hrl  hello_types.erl  hello_types.hrl

    打开hello_thrift.erl,里面就是:

    %%
    %% Autogenerated by Thrift Compiler (0.9.1)
    %%
    %% DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
    %%
    
    -module(hello_thrift).
    -behaviour(thrift_service).
    
    
    -include("hello_thrift.hrl").
    
    -export([struct_info/1, function_info/2]).
    
    struct_info('i am a dummy struct') -> undefined.
    %%% interface
    % say(This, Name)
    function_info('say', params_type) ->
      {struct, [{1, string}]}
    ;
    function_info('say', reply_type) ->
      string;
    function_info('say', exceptions) ->
      {struct, []}
    ;
    function_info(_Func, _Info) -> no_function.

    可以看到上面定义的say方法,在hello_thrift.erl里面有say方法的参数类型、返回类型,异常等信息。

    在hello.thrift里面没有定义任何类型,所以在 hello_types.erl没有任何实质内容。

    从上面的例子来看,产生erlang文件的思路是根据type以及service来命名。

    在gen-erl目录里面,新建一个hello_server2.erl文件,

    -module(hello_server2).
    -include("hello_thrift.hrl").
    -export([start/0, handle_function/2, say/1, stop/1]).
    
    
    debug(Info)->
        io:format("Debug info:~s~n",[Info]).
    
    say(Name)->
        io:format("~n Line:~p~n", [?LINE]),
        Sentence = "Hello," ++ Name,
        debug(Sentence),
        BinSentence = list_to_binary(Sentence),
        BinSentence.
    
    start()->
        start(9090).
    
    start(Port)->
        Handler = ?MODULE,
        thrift_socket_server:start([{handler, Handler},
                {service, hello_thrift},
                {port, Port},
                {name, hello_server}]).
    
    stop(Server)->
        thrift_socket_server:stop(Server).
    
    
    handle_function(Function, Args) when is_atom(Function), is_tuple(Args) ->
        case Function of
            say ->
                {reply, say(tuple_to_list(Args))};
            % add function here
            _ ->
                error
        end.

    如果参照这个hello_server2.erl和thrift-0.9.1/tutorial/erl/server.erl,可以发现他们的结构差不多。

    一般代码的思路是,使用thrift_socket_server:start/1函数来启动服务,导出handle_function/2函数来处理RPC访问。

    所以可以看出,一般的思路就是在thrift文件,里面添加需要导出的函数定义,然后在handle_function/2函数处添加额外的代码。thrift框架真的是节省了程序员的开发时间。

    使用erlang来做thrift的客户端开发,也比较容易,直接上代码:

    -module(hello_client).
    -include("hello_thrift.hrl").
    -export([test/0]).
    
    p(X)->
        io:format("in the p() ~w~n", [X]),
        ok.
    
    test()->
        Port = 9090,
        {ok, Client0} = thrift_client_util:new("localhost",
                Port,
                hello_thrift, []),
        io:format("~n Client0 : ~p~n", [Client0]),
        {Client1, Res} =  thrift_client:call(Client0, say, ["world"]),
        io:format(" the Res is ~p~n", [Res]),
        io:format("~n Client1 : ~p~n", [Client1]),
        p(Res),
        io:format("the Client0 == Client1: ~p~n", [Client0 == Client1]),
        thrift_client:close(Client1),
        ok.

    效果演示图:

  • 相关阅读:
    9、实战快速上手
    8、路由【前端实现页面的跳转】
    7、Webpack的学习【打包工具】
    6、vue的安装【nodejs、vue-cli】
    5、计算属性、内容分发、自定义事件
    4、Axios异步通信
    3、Vue表单的双向绑定以及第一个Vue组件
    2、Vue的基本属性
    PHP算法之寻找两个有序数组的中位数
    PHP算法之无重复字符的最长子串
  • 原文地址:https://www.cnblogs.com/getong/p/3509755.html
Copyright © 2011-2022 走看看