栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

linux基础操作之thrift

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

linux基础操作之thrift

1. 简介

        Apache Thrift软件框架用于可伸缩的跨语言服务开发,它将软件栈和代码生成引擎结合在一起,以构建在C++、Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk、OCaml和Delphi等语言之间高效、无缝地工作的服务。

        Thrift 采用IDL(Interface Definition Language)来定义通用的服务接口,然后通过Thrift提供的编译器,可以将服务接口编译成不同语言编写的代码,通过这个方式来实现跨语言的功能。

通过命令调用Thrift提供的编译器将服务接口编译成不同语言编写的代码

这些代码又分为服务端和客户端,将所在不同进程(或服务器)的功能连接起来

thrift -r --gen  

创建一个Thrift服务

  1. 定义服务接口(存放接口的文件夹就是thrift文件)

  2. 作为服务端的服务,需要生成server

  3. 作为请求端的服务,需要生成client

2. 案例:游戏的匹配服务 2.1 初始化git仓库

mkdir thrift_lesson
cd thrift_lesson
git init


mkdir thrift        # 存放 thrift 源文件
mkdir game          # 实现 游戏应用端 的 客户端 功能
mkdir match_system  # 实现 匹配系统服务器 的 服务端 和 客户端 功能


touch readme.md
# 远程创建好git上的repo
git remote add origin git@git.acwing.com:lansfair/thrift_learning.git
git add .
git commit -m "init repo"
git push -u origin master

2.2 初步实现 游戏应用端 与 匹配系统服务器 的交互 2.2.1 创建 match.thrift 接口文件

match.thrift:用于实现 游戏应用端 与 匹配系统服务器 交互的 service

namespace cpp match_service //声明转换为C++语言


struct User {   //定义结构体 User
    1: i32 id, 
    2: string name,
    3: i32 score
}


service Match { //定义service服务
      


    i32 add_user(1: User user, 2: string info),


      


    i32 remove_user(1: User user, 2: string info),
}

2.2.2 匹配系统的服务端

利用match.thrift接口文件生成C++的匹配系统服务端

  1. 进入 match_system 中新建文件夹 src (之后所有的 匹配服务器 源文件放在 src 下)

  2. 并在 src 文件夹中运行 thrift 脚本生成 C++ 版本的文件

# 原始的thrift生成文件语法:thrift -r --gen  
mkdir match_system/src
cd match_system/src
thrift -r --gen cpp ../../thrift/match.thrift


# 将该文件夹重命名为 match_server(区别于之后要此处生成的client server)
# match_server 与 游戏应用端交互 ; client_server 与 数据存储服务器交互
mv gen-cpp match_server


# 把 Match_server.skeleton.cpp 移动到当前 src 目录下并重命名为 main.cpp
# 方便之后调试 main.cpp 文件,其他的源文件仍被存放在 src 文件夹下
mv match_server/Match_server.skeleton.cpp main.cpp


# 移动后,需要修改一下 main.cpp 中头文件里Math.cpp 的引用路径
# 并且先暂时让main.cpp中的函数return 0

生成完成后的工作区路径

编译并运行 cpp 文件

# 1. 编译 所有的 .cpp 文件生成 .o 文件
# g++ -c [文件1.cpp] [文件2.cpp] ...
g++ -c main.cpp match_server
    i32 save_data(1: string username, 2: string password, 3: i32 player1_id, 4: i32 player2_id)
}

在 匹配系统服务器 利用 thrift 生成 C++ 文件

并删掉不必要 服务端 文件,因为在该交互功能里,匹配系统服务器 是作为客户端的(C++ 只能有一个main函数)

cd match_system/src
thrift -r --gen cpp ../../thrift/save.thrift
mv gen-cpp save_client
rm save_client/Save_server.skeleton.cpp

利用 md5 哈希函数获得服务器密码的 哈希值

md5sum


xxxxxxx []
[Ctrl + D]
# 哈希值前 8 位就是我们要调用服务器接口时用的密码

从 thrift官网 复制 Client 端的模板到 main.cpp 下与 数据存储服务器 交互的函数中

(数据存储服务器已经写好了相关服务并开启)

// 需要额外引入的头文件
#include 
#include 


// 需要额外声明的命名空间
using namespace  ::save_service;


//重写 save_result 内的内容,使其能够与 "数据存储服务器" 交互
void save_result(int a, int b)  // 记录成功匹配的信息
{
    printf("Match Result: %d %dn", a, b);


    // Client端的板子
    std::shared_ptr socket(new TSocket("123.57.47.211", 9090));
    std::shared_ptr transport(new TBufferedTransport(socket));
    std::shared_ptr protocol(new TBinaryProtocol(transport));
    SaveClient client(protocol);


    try {
        transport->open();


        //调用接口,把信息存储 "数据存储服务器" 中
        int res = client.save_data("acs_2511", "ac046a27", a, b);
        //输出匹配结果
        if (!res) puts("success");
        else puts("fail");


        transport->close();
    } catch (TException& tx) {
        cout << "ERROR: " << tx.what() << endl;
    }
}

编译,运行,上传

g++ -c main.cpp save_client
            return new MatchHandler;
        }
        void releaseHandler(MatchIf* handler) override {    //改为MatchIf*  
            delete handler;
        }
};
// 重写main函数,启用多线程服务器
int main(int argc, char **argv) {
    TThreadedServer server(
            std::make_shared(std::make_shared()),
            std::make_shared(9090), //port
            std::make_shared(),
            std::make_shared());


    cout << "Start Match Server" << endl;


    thread matching_thread(consume_task);   // 调用一个线程运行 consume_task


    server.serve();


    return 0;
}

编译,运行,上传

g++ -c main.cpp
g++ *.o -o main -lthrift -pthread
./main


# 上传到 git 服务器
git add main.cpp
git commit -m "match server:4.0"
git push

2.5 匹配系统 5.0

随时间扩大匹配域:用额外一个数组 wt 来记录每个用户的等待时间,在消息队列为空时,线程会每 1 秒调用一次 match 函数,然后每次调用 match 函数,会首先对 匹配池中所有用户的 wt 值自增 1,从而实现用 wt 记录每个用户的等待时间,然后,每一单位的 wt 会扩大 50分 的匹配域。

修改main.cpp

// 主要修改的是 pool 类中关于 match 函数的部分
class Pool
{
public:
    ....
    bool check(int i, int j)
    {
        User a = users[i], b = users[j];
        int diff = abs(a.score - b.score);
        int a_diff_max = wt[i] * 50; 
        int b_diff_max = wt[j] * 50; 
        return diff <= a_diff_max && diff <= b_diff_max;
    }
    void match()    // 匹配池中的第一、第二个用户进行匹配
    {
        // 每 1 秒调用 1 次 match,实现 wt 自增 1,从而实现使所有用户等待时间增加
        for (auto &t: wt) 
            t ++ ;


        while (users.size() > 1)
        {
            bool flag = true;
            for (uint32_t i = 0; i < users.size(); i ++ )
            {
                for (uint32_t j = i + 1; j < users.size(); j ++ )
                {
                    if (check(i, j)) 
                    {
                        users.erase(users.begin() + j); 
                        users.erase(users.begin() + i); 
                        wt.erase(wt.begin() + j); 
                        wt.erase(wt.begin() + i); 


                        save_result(users[i].id, users[j].id);
                        flag = false;
                        break;
                    }
                    if (!flag) break;
                }
            }
            if (flag) break;    // 一轮扫描后,发现没有能够匹配的用户,就停止扫描,等待下次调用
        }
    }
    ....
private:
    ....
    vector wt; //wait_time 记录每个用户的等待时间
}pool;

编译,运行,上传

g++ -c main.cpp
g++ *.o -o main -lthrift -pthread
./main
# 上传到 git 服务器
git add main.cpp
git commit -m "match server:5.0"
git push

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/830125.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号