前言
因为工作上需要开发一款C/S架构的软件, 在客户端和服务器之间通信方式上, 经过几番思考之后决定采用thrift 库作为通信工具.
thrift 库的设计理念
thrift库的调用采用的函数接口的方式, 设计者设计之初希望将网络传输层, 和数据协议层彻底隔离. 网络通信的使用如同在本地调用一样. 这种设计理念是非常惊艳的. 让开发者更加专注于业务逻辑上. 这也意味着thrift 库的 同步调用将成主流. 对于网络通信而言, 同步通信曾经是挥之不去的噩梦. 但是thrift 却提供了一种非常优雅的方式处理: 将所有网络通信问题封装成异常.
thrift 开发常见问题
thrift 身份认知机制
thrift 本身并没有提供身份识别机制. 服务器本身无法自动识别客户端身份. 开发者如果需要实现身份识别机制, 则需要在每个接口函数上提供身份识别ID.
例如: sayHi(const string t_ssid );
t_ssid 即为身份识别ID. ssid 在客户端第一次连接服务器时, 由服务器生成的特定字符串特征码. 客户端和服务端各存一份. 客户端向服务端申请服务时 服务端即可根据客户端所提供的ID 信息, 选择是否提供服务.
大数据传输
thrift 库本身支持常用基础的类型, 数据结构, 类为了实现大数据量的传输, 例如需要将一张数据库表传输出去, 单纯使用数据结构是非常糟糕的. 这时候就必须考虑数据序列化的处理方式. 例如将一个类的数据全部转化成 json 格式的string进行传输.
笔者做过一个基本的测试, 将size为10W 的string类型传输到服务器,在回传到客户端 , thrift 均可以完全胜任
主动抛出异常
由于thrift接口不支持引用,或者指针, 接口层仅接受一个参数作为返回值. 由于返回参数本身需要负责数据的传输工作, 将错误信息通过返回参数方式显然太过奢侈.同时也将大大增加编程的复杂程度. 由于thrift 支持用户自定义异常, 对于可使用主动抛出异常的方式来传输错误信息.
接口异常被动保护机制
由于thrift 每次在返回前都会捕获异常. 用户自定义异常放行. 其他异常将主动捕捉,并且报错. 报错后服务器将对当前客户端连接拒绝服务器, 甚至导致整个thift 服务器服务器卡死的情况发生. 这也就要求开发者在服务器端要求有着严格的异常保护机制. 由于thrift服务器异常错误将无法提供错误触发原因. 将导致软件异常难以调试. 笔者的做法是在thrift层执行 std::exception 异常捕获. 主动将所有非用户自定义异常捕获, 并且将程序 abort()掉.以方便快速定位软件错误.
客户端多线程保护机制
客户端的thrift 客户端调用本身不具备多线程的保护机制. 在客户端使用多线程通信时, 开发者需要使用多线程保护机制. 否则服务器非常容易被客户端引发异常错误. 导致拒绝服务
C++ 兼容XP 系统
由于thrift 默认使用了WIN7 的网络通信库, 导致thrift无法兼容XP. 笔者使用的thrift 0.9.2 版本库, 在XP 下运行时, 系统提示无法定位 WS2_32.dll , 经过多番讨论和源码研究之后, 发现这是官方的一个bug所致. 之前也有很多人提及到这个bug的存在, 但是因为国外 XP的覆盖率太低, 这个bug 到thrift 0.9.3 均未解决.
thrift 兼容XP 系统的解决方案
首先定位thrift源码中的
thrift-0.9.2\lib\cpp\src\thrift\windows\WinFcntl.cpp
此文件根据系统的版本的不同, 定义不同的网络通信方案. 通过源码可得知,其实官方的thrift在开发之初是有直接支持XP 系统的, 只是因为bug 的原因, 所有的系统均调用了
* WSAPoll(fdArray, nfds, timeout);* 这个函数, 导致软件无法在XP运行.
既然知道了这个原因, 从最小修改代码的角度出发, 既然thrift 源码无法对系统 _WIN32_WINNT 有效的识别, 那么直接强制thrift 均采用 XP 模式下的网络通信方案,即可解决兼容XP 的问题
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
兼容性方案总结
通过屏蔽以上几行代码, 亲测可实现兼容XP 的功能. 但是听大神提示说, XP 模式下的网络效率 比 采用 WIN7 WSAPoll(fdArray, nfds, timeout); 系统库的效率要低. 毕竟XP 是2000年的产品.
通过探讨交流, 有大神提出在现有的基础直接采用boost 网络库的方案, 以解决通信效率的问题.