网站建设上传和下载企业网站建设中存在的问题分析

当前位置: 首页 > news >正文

网站建设上传和下载,企业网站建设中存在的问题分析,浙江核酸检测查验,怎么制作公司自己网站1. 简介 Apache Thrift软件框架用于可伸缩的跨语言服务开发#xff0c;它将软件栈和代码生成引擎结合在一起#xff0c;以构建在C、Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk、OCaml和Delphi等语言之间高效、无缝地工作的…

  1. 简介 Apache Thrift软件框架用于可伸缩的跨语言服务开发它将软件栈和代码生成引擎结合在一起以构建在C、Java、Python、PHP、Ruby、Erlang、Perl、Haskell、C#、Cocoa、JavaScript、Node.js、Smalltalk、OCaml和Delphi等语言之间高效、无缝地工作的服务。 Thrift 采用IDLInterface Definition Language来定义通用的服务接口然后通过Thrift提供的编译器可以将服务接口编译成不同语言编写的代码通过这个方式来实现跨语言的功能。 通过命令调用Thrift提供的编译器将服务接口编译成不同语言编写的代码 这些代码又分为服务端和客户端将所在不同进程(或服务器)的功能连接起来 thrift -r –gen language Thrift filename创建一个Thrift服务 定义服务接口(存放接口的文件夹就是thrift文件) 作为服务端的服务需要生成server 作为请求端的服务需要生成client

  2. 案例游戏的匹配服务 2.1 初始化git仓库 mkdir thrift_lesson cd thrift_lesson git initmkdir thrift # 存放 thrift 源文件 mkdir game # 实现 游戏应用端 的 客户端 功能 mkdir match_system # 实现 匹配系统服务器 的 服务端 和 客户端 功能touch readme.md

    远程创建好git上的repo

    git remote add origin gitgit.acwing.com:lansfair/thrift_learning.git git add . git commit -m init repo git push -u origin master2.2 初步实现 游戏应用端 与 匹配系统服务器 的交互 2.2.1 创建 match.thrift 接口文件 match.thrift用于实现 游戏应用端 与 匹配系统服务器 交互的 service namespace cpp match_service //声明转换为C语言struct User { //定义结构体 User1: i32 id, 2: string name,3: i32 score }service Match { //定义service服务/** * user: 添加的用户信息* info: 附加信息* 在匹配池中添加一个名用户*/ i32 add_user(1: User user, 2: string info),/** * user: 删除的用户信息* info: 附加信息* 从匹配池中删除一名用户*/ i32 remove_user(1: User user, 2: string info), }2.2.2 匹配系统的服务端 利用match.thrift接口文件生成C的匹配系统服务端 进入 match_system 中新建文件夹 src 之后所有的 匹配服务器 源文件放在 src 下 并在 src 文件夹中运行 thrift 脚本生成 C 版本的文件 # 原始的thrift生成文件语法thrift -r –gen language Thrift filename 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/*.cpp# 2. 链接 所有的 .o 文件生成可执行文件 .exe

    g [文件1.o] [文件2.o] … -o [需要额外添加的动态库]

    此处需要额外添加 -lthrift 的 thrift 动态库

    g *.o -o main -lthrift# 3. 运行 可执行文件 ./main将代码提交到git git add . git restore –stage *.o # .o文件是编译文件不加入暂存区里 git restore –stage main # main是可执行文件不加入暂存区里 git commit -m add match server git push2.2.3 匹配系统的客户端 在 game 文件夹下利用match.thrift接口文件生成python的匹配系统的客户端 # 原始的thrift生成文件语法thrift -r –gen language Thrift filename mkdir game/src cd game/src thrift -r –gen py ../../thrift/match.thrift# 将该文件夹重命名为 match_client

    不过这里不改也无所谓游戏应用端只有匹配的客户端

    mv gen-py match_client# 删掉 Match_remote

    该文件是用 py 实现 服务端 时用的文件

    此处我们只需要实现 客户端 功能因此他没有作用可以删去

    rm match_client/match/Match-remote利用官网提供的模板编写 客户端 文件 client.py # 先删去开头三行声明

    此处修改路径以及Calculator 为 Match

    此处修改 ttypes 路径 以及 User 类

    from match_client.match import Match from match_client.match.ttypes import Userfrom thrift import Thrift from thrift.transport import TSocket from thrift.transport import TTransport from thrift.protocol import TBinaryProtocoldef main():# Make sockettransport TSocket.TSocket(localhost, 9090)# Buffering is critical. Raw sockets are very slowtransport TTransport.TBufferedTransport(transport)# Wrap in a protocolprotocol TBinaryProtocol.TBinaryProtocol(transport)# Create a client to use the protocol encoderclient Match.Client(protocol)# Connect!transport.open()# 调试语句user User(1, yxc, 1500)client.add_user(user, ) # Close!transport.close()# 调用 main 函数 if name main:main() 此时服务之间已经可以交互 同样将代码文件提交到git git add . git restore –stage *.pyc # .pyc文件是编译文件不加入暂存区里 git restore –stage *.swp # .swp文件是缓存文件不加入暂存区里vim没关时会生成 git commit -m add client git push2.3 匹配系统2.0 2.3.1 重写 client.py 重写 client.py使之能不断从终端里读入信息 # 利用 python 在终端读入信息需要引入 stdin from sys import stdin# 将原来的通信 main 函数改写成operate函数每次需要的时候调用一次建立通信传递信息

    目的是可以一直不断处理信息

    然后重写 main 函数使之能不断从终端读入信息

    def operate(op, user_id, user_name, score):# ………………………# 针对 op 参数分别进行 增加 与 删出 操作user User(user_id, user_name, score)if op add:client.add_user(user, )else:client.remove_user(user, )# ………………………def main():for line in stdin:op, user_id, user_name, score line.split( )operate(op, int(user_id), user_name, int(score))2.3.2 在匹配服务器里给 匹配系统 开一个 线程 操作系统 里的 PV 原语 生产者-消费者 模型 // This autogenerated skeleton file illustrates how to build a server. // You should copy it to another filename to avoid overwriting it.#include match_server/Match.h #include thrift/protocol/TBinaryProtocol.h #include thrift/server/TSimpleServer.h #include thrift/transport/TServerSocket.h #include thrift/transport/TBufferTransports.h#include iostream #include thread // 需要线程引入头文件 #include mutex // 互斥信号量 #include condition_variable // 条件变量用于 阻塞和唤醒 线程 #include queue // 用于模拟消息队列 #include vectorusing namespace ::apache::thrift; using namespace ::apache::thrift::protocol; using namespace ::apache::thrift::transport; using namespace ::apache::thrift::server;using namespace ::match_service;using namespace std;struct Task //消息队列中的元素 {User user;string type; };struct MessageQueue //消息队列 {queueTask q; //消息队列本体mutex m; //互斥信号量condition_variable cv; //条件变量用于阻塞唤醒线程 }message_queue;class Pool // 模拟匹配池 { public:void save_result(int a, int b) // 记录成功匹配的信息{printf(Match Result: %d %d\n, a, b);}void match() // 匹配池中的第一、第二个用户进行匹配{while (users.size() 1){auto a users[0], b users[1];users.erase(users.begin());users.erase(users.begin());save_result(a.id, b.id);}}void add(User user) // 向匹配池中加入用户{users.push_back(user);}void remove(User user) // 从匹配池中删除用户{for (uint32_t i 0; i users.size(); i ){if (users[i].id user.id){users.erase(users.begin() i);break;}}}private:vectorUser users; // 匹配池中的用户用 vector 记录 }pool;class MatchHandler : virtual public MatchIf {public:MatchHandler() {// Your initialization goes here}int32_t add_user(const User user, const std::string info) {// Your implementation goes hereprintf(add_user\n);unique_lockmutex lck(message_queue.m); // 访问临界区(消息队列)先上锁message_queue.q.push({user, add}); // 把新消息加入消息队列message_queue.cv.notify_all(); // 唤醒阻塞的线程return 0;}int32_t remove_user(const User user, const std::string info) {// Your implementation goes hereprintf(remove_user\n);unique_lockmutex lck(message_queue.m); // 访问临界区(消息队列)先上锁message_queue.q.push({user, remove}); // 把新消息加入消息队列message_queue.cv.notify_all(); // 唤醒阻塞的线程return 0;}};// 基于 生产者-消费者模型 的线程 void consume_task() {while (true){unique_lockmutex lck(message_queue.m); // 访问临界区(消息队列)先上锁if (message_queue.q.empty()){message_queue.cv.wait(lck); //这里要阻塞进程// 避免队列为空时一直反复运行该线程导致一直占用临界区而不能加入新消息}else{auto task message_queue.q.front(); // 取出消息队列队头元素message_queue.q.pop();lck.unlock(); // 临界区访问结束直接解锁// 避免后续没用到临界区信息而长时间占用临界区的情况发生if (task.type add) pool.add(task.user);else if (task.type remove) pool.remove(task.user);pool.match();}} }int main(int argc, char argv) {int port 9090;::std::shared_ptrMatchHandler handler(new MatchHandler());::std::shared_ptrTProcessor processor(new MatchProcessor(handler));::std::shared_ptrTServerTransport serverTransport(new TServerSocket(port));::std::shared_ptrTTransportFactory transportFactory(new TBufferedTransportFactory());::std::shared_ptrTProtocolFactory protocolFactory(new TBinaryProtocolFactory());TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);cout Start Match Server endl;thread matching_thread(consume_task); // 调用一个线程运行 consume_taskserver.serve();return 0; }同样编译上传到git运行现在已经能初步实现匹配功能 g -c main.cpp g *.o -o main -lthrift -pthreadgit add main.cpp git commit -m match-server ver:2.0 git push2.3.3 数据存储服务客户端 创建一个数据存储服务将匹配结果存储到指定的服务器的文件中 创建数据存储的thrift接口:save.thrift namespace cpp save_serviceservice Save {/* username: myserver的名称* password: myserver的密码的md5sum的前8位* 用户名密码验证成功会返回0验证失败会返回1* 验证成功后结果会被保存到myserver:homework/lesson_6/result.txt中*/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 哈希函数获得服务器密码的 哈希值 md5sumxxxxxxx [Enter] [Ctrl D]

    哈希值前 8 位就是我们要调用服务器接口时用的密码从 thrift官网 复制 Client 端的模板到 main.cpp 下与 数据存储服务器 交互的函数中

    数据存储服务器已经写好了相关服务并开启 // 需要额外引入的头文件 #include thrift/transport/TSocket.h #include thrift/transport/TTransportUtils.h// 需要额外声明的命名空间 using namespace ::save_service;//重写 save_result 内的内容使其能够与 数据存储服务器 交互 void save_result(int a, int b) // 记录成功匹配的信息 {printf(Match Result: %d %d\n, a, b);// Client端的板子std::shared_ptrTTransport socket(new TSocket(123.57.47.211, 9090));std::shared_ptrTTransport transport(new TBufferedTransport(socket));std::shared_ptrTProtocol 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/*.cpp g *.o -o main -lthrift -pthread ./main此时运行匹配系统匹配成果后匹配数据将保存到数据存储服务器 # 上传到 git 服务器 git add main.cpp git add ../../thrift/save.thrift git commit -m 2.0: implement save-client git push2.4 匹配系统3.0 增加功能每次只匹配分差小于 50 的用户 由于我们的匹配策略发生了变化可能匹配池中仍然有用户在等待匹配当前匹配池各个用户分差都大于50而消息队列此时仍为空需要修改线程中消息队列为空时不再是阻塞 直到唤醒为止而是每经过 1 秒就进行一次 match() 调用如果仍然采用先前的策略可能会导致进程卡死新用户不进去老用户永远匹配不了 //引入调用 sleep 函数的头文件 #include unistd.h// 用于调用 sleep 函数//修改 生产者 - 消费者模型 的线程中关于消息队列为空时的处理 if (message_queue.q.empty()) {// 此处修改为每 1 秒进行一次匹配而不是等到被唤醒时才匹配lck.unlock(); // 直接解锁临界区资源pool.match(); //调用math()sleep(1); }//重写匹配池Pool类中的match函数使之可以匹配分数差在 50 以内的两个用户 void match() // 匹配池中的第一、第二个用户进行匹配 {while (users.size() 1){// 按照 rank分 排序sort(users.begin(), users.end(), {return a.score b.score;});bool flag true;for (uint32_t i 1; i users.size(); i ){User a users[i - 1], b users[i];// 两名玩家分数差小于50时进行匹配if (b.score - a.score 50){users.erase(users.begin() i - 1, users.begin() i); //删掉用户a,bsave_result(a.id, b.id);flag false;break;}}if (flag) break; // 一轮扫描后发现没有能够匹配的用户就停止扫描等待下次调用} }g -c main.cpp g .o -o main -lthrift -pthread ./main# 上传到 git 服务器 git add main.cpp git add ../../thrift/save.thrift git commit -m match server:3.0 git push2.4 匹配系统4.0 加入多线程 重写 main.cpp 文件 // 引入新的多线程头文件 #include thrift/concurrency/ThreadManager.h #include thrift/concurrency/ThreadFactory.h #include thrift/server/TThreadPoolServer.h #include thrift/server/TThreadedServer.h #include thrift/TToString.h// 复制模板的类 CalculatorCloneFactory 然后改一改把所有的 Calculator 改为 Match class MatchCloneFactory : virtual public MatchIfFactory {public:~MatchCloneFactory() override default;MatchIf getHandler(const ::apache::thrift::TConnectionInfo connInfo) override{std::shared_ptrTSocket sock std::dynamic_pointer_castTSocket(connInfo.transport);/cout Incoming connection\n;cout \tSocketInfo: sock-getSocketInfo() \n;cout \tPeerHost: sock-getPeerHost() \n;cout \tPeerAddress: sock-getPeerAddress() \n;cout \tPeerPort: sock-getPeerPort() \n;/return new MatchHandler;}void releaseHandler(MatchIf* handler) override { //改为MatchIf* delete handler;} }; // 重写main函数启用多线程服务器 int main(int argc, char **argv) {TThreadedServer server(std::make_sharedMatchProcessorFactory(std::make_sharedMatchCloneFactory()),std::make_sharedTServerSocket(9090), //portstd::make_sharedTBufferedTransportFactory(),std::make_sharedTBinaryProtocolFactory());cout Start Match Server endl;thread matching_thread(consume_task); // 调用一个线程运行 consume_taskserver.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 push2.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:….vectorint 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