当前位置:   article > 正文

优秀开源项目C++高性能服务器引擎sogou/workflow学习笔记1-环境配置篇_搜狗workflow查看源码 windows vs

搜狗workflow查看源码 windows vs

created: 2020-11-05 11:39:27
2010年上大二,我认定了C++,于是一直专攻C++。第一份工作也如愿找到了windows环境下的C++开发,然而只做了一年,后续由于工作变动,一直在用python/ruby/javascript,偶尔也会用下QT,纯正的C++被尘封了很多年,导致我的这把利器有些生锈。于是,近期打算把它捡起来好好磨磨。机缘巧合之下,了解到搜狗开源的C++服务器引擎sogou/workflow,轻盈优雅,且支撑后端几乎所有的C++在线业务,每日处理请求百亿次,一下子就打动我了,非常喜欢,打算花几个月时间啃透,学习一下优秀团队的编程思想、设计思路。
由于sogou/workflow项目官方没有出相应的安装配置说明,我自己摸索了很久才跑通第一个用例。在我做笔记的时候,我意识到,这个问题会过滤掉很多刚入行不久的伙伴,因为通常学习使用一个项目,第一步就是把它跑起来。那么,我就做个引路人,介绍一下环境如何配置,让用例跑起来,供大家参考。

项目介绍

https://github.com/sogou/workflow.git
https://zhuanlan.zhihu.com/p/165638263
https://www.oschina.net/p/sogou-cpp-workflow

我的环境

  • centos7
  • debian9

注:以上两个环境均可正常运行。

项目依赖工具

  • cmake >=3.6
  • gcc/g++/clang++
  • OpenSSL >= 1.1

让我们开始探索

1. 下载源码到指定目录~/workflow

# git clone https://github.com/sogou/workflow.git# mkdir ~/workflow
# git clone --recursive https://github.com/sogou/workflow.git ~/workflow
  • 1
  • 2
  • 3
  • 4

2. 编译安装cmake指定版本

下载cmake源码
# wget -P ~/Downloads -c https://cmake.org/files/v3.12/cmake-3.12.1.tar.gz
  • 1

注意,不建议直接下载cmake-3.12.1-Linux-x86_64.tar.gz,这个是已经编译好的版本。
使用cmake-3.12.1.tar.gz比较好,下载后再make编译,这样安装后与本机的兼容性更好。

解压源码
# mkdir ~/cmake3
# tar -zxvf cmake-3.12.1.tar.gz -C ~/cmake3
  • 1
  • 2
编译安装
# cd ~/cmake3/cmake3-3.12.1
# ./configure
# make && make install
  • 1
  • 2
  • 3

当前目录下将生成bin/目录,里面是可执行程序。

当然,如果你想节省时间,用编译后的也不失为一个方法。(文件大概33M)

# wget -P ~/Downloads -c https://cmake.org/files/v3.12/cmake-3.12.1-Linux-x86_64.tar.gz
# tar -zxvf cmake-3.12.1-Linux-x86_64.tar.gz -C ~/cmake3
  • 1
  • 2
添加到环境变量
# export PATH="$PATH:$HOME/cmake3/cmake3-3.12.1/bin"
# echo $PATH
/root/.bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/cmake3/cmake-3.12.1/bin
  • 1
  • 2
  • 3
查看cmake版本,验证是否安装成功
# cmake --version
cmake version 3.12.1

CMake suite maintained and supported by Kitware (kitware.com/cmake).
  • 1
  • 2
  • 3
  • 4

3. 编译sogou/workflow

# cd ~/workflow
# ./configure
./configure: line 2: cmake3: command not found
CMAKE_C_FLAGS_DEBUG is -g
CMAKE_C_FLAGS_RELEASE is -O3 -DNDEBUG
CMAKE_C_FLAGS_RELWITHDEBINFO is -O2 -g -DNDEBUG
CMAKE_C_FLAGS_MINSIZEREL is -Os -DNDEBUG
CMAKE_CXX_FLAGS_DEBUG is
CMAKE_CXX_FLAGS_RELEASE is
CMAKE_CXX_FLAGS_RELWITHDEBINFO is
CMAKE_CXX_FLAGS_MINSIZEREL is
-- Configuring done
-- Generating done
-- Build files have been written to: /root/workflow

# make
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

生成_include和_lib两个目录,前者是头文件,后者是静态库和动态库

4. 手动编译学习用例tutorial-01-wget.cc

# cd ~/opensource/workflow
# clang++ -std=c++11 -Wall tutorial/tutorial-01-wget.cc -I _include/ _L _lib/ -lworkflow -lssl -lcrypto -lpthread -o twget
# ./twget www.sougou.com
  • 1
  • 2
  • 3

遇坑过程

# clang++ tutorial/tutorial-01-wget.cc -o twget
报错:
clang++ tutorial/tutorial-01-wget.cc 
tutorial/tutorial-01-wget.cc:25:10: fatal error: 'workflow/HttpMessage.h' file not found
#include "workflow/HttpMessage.h"
         ^
1 error generated.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
clang++ -std=c++11 -Wall tutorial/tutorial-01-wget.cc -I _include/ -o twget
报错:
/data/tmp/tutorial-01-wget-f47913.o: In function `wget_callback(WFNetworkTask<protocol::HttpRequest, protocol::HttpResponse>*)':
tutorial/tutorial-01-wget.cc:(.text+0x29c): undefined reference to `protocol::HttpHeaderCursor::next(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
tutorial/tutorial-01-wget.cc:(.text+0x428): undefined reference to `protocol::HttpHeaderCursor::next(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&)'
/data/tmp/tutorial-01-wget-f47913.o: In function `main':
tutorial/tutorial-01-wget.cc:(.text+0x79e): undefined reference to `WFTaskFactory::create_http_task(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, int, int, std::function<void (WFNetworkTask<protocol::HttpRequest, protocol::HttpResponse>*)>)'
/data/tmp/tutorial-01-wget-f47913.o: In function `protocol::RedisValue::~RedisValue()':
tutorial/tutorial-01-wget.cc:(.text._ZN8protocol10RedisValueD2Ev[_ZN8protocol10RedisValueD2Ev]+0x14): undefined reference to `protocol::RedisValue::free_data()'
/data/tmp/tutorial-01-wget-f47913.o: In function `EncodeStream::~EncodeStream()':
tutorial/tutorial-01-wget.cc:(.text._ZN12EncodeStreamD2Ev[_ZN12EncodeStreamD2Ev]+0xd): undefined reference to `EncodeStream::clear_buffer()'
/data/tmp/tutorial-01-wget-f47913.o: In function `protocol::RedisMessage::~RedisMessage()':
tutorial/tutorial-01-wget.cc:(.text._ZN8protocol12RedisMessageD2Ev[_ZN8protocol12RedisMessageD2Ev]+0x27): undefined reference to `redis_parser_deinit'
/data/tmp/tutorial-01-wget-f47913.o: In function `protocol::HttpMessage::get_parsed_body(void const**, unsigned long*) const':
tutorial/tutorial-01-wget.cc:(.text._ZNK8protocol11HttpMessage15get_parsed_bodyEPPKvPm[_ZNK8protocol11HttpMessage15get_parsed_bodyEPPKvPm]+0x25): undefined reference to `http_parser_get_body'
/data/tmp/tutorial-01-wget-f47913.o: In function `protocol::HttpMessage::add_header_pair(char const*, char const*)':
tutorial/tutorial-01-wget.cc:(.text._ZN8protocol11HttpMessage15add_header_pairEPKcS2_[_ZN8protocol11HttpMessage15add_header_pairEPKcS2_]+0x5d): undefined reference to `http_parser_add_header'
/data/tmp/tutorial-01-wget-f47913.o: In function `WFCounterTask::done()':
tutorial/tutorial-01-wget.cc:(.text._ZN13WFCounterTask4doneEv[_ZN13WFCounterTask4doneEv]+0x74): undefined reference to `SeriesWork::pop()'
/data/tmp/tutorial-01-wget-f47913.o: In function `WFCounterTask::count()':
tutorial/tutorial-01-wget.cc:(.text._ZN13WFCounterTask5countEv[_ZN13WFCounterTask5countEv]+0x3b): undefined reference to `SubTask::subtask_done()'
/data/tmp/tutorial-01-wget-f47913.o: In function `WFGenericTask::dispatch()':
tutorial/tutorial-01-wget.cc:(.text._ZN13WFGenericTask8dispatchEv[_ZN13WFGenericTask8dispatchEv]+0x18): undefined reference to `SubTask::subtask_done()'
/data/tmp/tutorial-01-wget-f47913.o: In function `WFGenericTask::done()':
tutorial/tutorial-01-wget.cc:(.text._ZN13WFGenericTask4doneEv[_ZN13WFGenericTask4doneEv]+0x43): undefined reference to `SeriesWork::pop()'
/data/tmp/tutorial-01-wget-f47913.o: In function `Workflow::start_series_work(SubTask*, std::function<void (SeriesWork const*)>)':
tutorial/tutorial-01-wget.cc:(.text._ZN8Workflow17start_series_workEP7SubTaskSt8functionIFvPK10SeriesWorkEE[_ZN8Workflow17start_series_workEP7SubTaskSt8functionIFvPK10SeriesWorkEE]+0x47): undefined reference to `SeriesWork::SeriesWork(SubTask*, std::function<void (SeriesWork const*)>&&)'
/data/tmp/tutorial-01-wget-f47913.o: In function `WFFuture<void>::wait() const':
tutorial/tutorial-01-wget.cc:(.text._ZNK8WFFutureIvE4waitEv[_ZNK8WFFutureIvE4waitEv]+0x49): undefined reference to `WFGlobal::get_scheduler()'
tutorial/tutorial-01-wget.cc:(.text._ZNK8WFFutureIvE4waitEv[_ZNK8WFFutureIvE4waitEv]+0x6c): undefined reference to `WFGlobal::sync_operation_begin()'
tutorial/tutorial-01-wget.cc:(.text._ZNK8WFFutureIvE4waitEv[_ZNK8WFFutureIvE4waitEv]+0x87): undefined reference to `WFGlobal::sync_operation_end()'
/data/tmp/tutorial-01-wget-f47913.o: In function `CommScheduler::is_handler_thread()':
tutorial/tutorial-01-wget.cc:(.text._ZN13CommScheduler17is_handler_threadEv[_ZN13CommScheduler17is_handler_threadEv]+0x15): undefined reference to `Communicator::is_handler_thread()'
/data/tmp/tutorial-01-wget-f47913.o:(.rodata._ZTVN8protocol12RedisMessageE[_ZTVN8protocol12RedisMessageE]+0x10): undefined reference to `protocol::RedisMessage::encode(iovec*, int)'
/data/tmp/tutorial-01-wget-f47913.o:(.rodata._ZTVN8protocol12RedisMessageE[_ZTVN8protocol12RedisMessageE]+0x28): undefined reference to `protocol::RedisMessage::append(void const*, unsigned long*)'
/data/tmp/tutorial-01-wget-f47913.o:(.rodata._ZTVN8protocol12RedisMessageE[_ZTVN8protocol12RedisMessageE]+0x48): undefined reference to `non-virtual thunk to protocol::RedisMessage::append(void const*, unsigned long*)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
  • 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

最终:

# clang++ -std=c++11 -Wall tutorial/tutorial-01-wget.cc -I _include/ -L _lib/ -lworkflow -o twget# clang++  -std=c++11 -Wall tutorial/tutorial-01-wget.cc  -I _include/ -L _lib -lworkflow -lssl -lcrypto -lpthread  -o twget
  • 1
  • 2
  • 3

OK,成功编译

然而,有更简单的办法。。。

5. 自动编译

官方提供了CMake,直接到tutorial/目录下执行make即可生成所有用例的可执行程序。

6. 运行程序

# ./twget sogou.com
  • 1

打印出html内容。

结束语

好了,可以开始我们的学习之旅啦。如果帮到你了,请点个赞或者评论一下,让更多人的知道,少走弯路。
(全文完)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/66868
推荐阅读
相关标签
  

闽ICP备14008679号