1 Star 0 Fork 75

俄语的呀泪 / da4qi4_public

forked from zhuangyan-stone / da4qi4_public 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README
Apache-2.0

零、几个原则

0.1 自己的狗粮自己吃

官网 第2学堂 www.d2school.com 后台使用 da4qi4作为Web Server开发。(nginx + da4qi4 + redis + mysql)。 给一个在手机上运行的网站效果:

第2学堂手机版

丑,但这只和我的美感太差有关,和后台使用什么Web框架一分钱关系都没有。

0.2 牛人的大腿抱真香

使用成熟的,广泛应用(最好有大公司参与)的开源项目作为框架基础组成部件。

da4qi4 Web 框架优先使用成熟的、C/C++开源项目的搭建。其中:

  • HTTP 基础协议解析:Node.JS的底层C组件 Node.JS / http-parser, nodejs/http-parser
  • HTTP multi-part : multipart-parsr multipart-parser-c
  • 网络异步框架: C++ boost.asio boostorg/asio (预计进入C++ 2x标准库)
  • JSON : nlohmann-json JSON for Modern C++ (github上搜索JSON,所有语言中暂排第一个)
  • 日志: splogs 一个高性能的C++日志库 (微软公司选择将它绑定到 Node.JS 作日志库)
  • 模板引擎: inja 是模板引擎 Jinja 的 C++ 实现版本,和 nlohmann-json 完美配合实现C++内嵌的动态数据结构
  • Redis 客户端: 基于nekipelov/redisclient,为以类node.js访问redis进行专门优化(实现单线程异步访问,去锁)。 da4qi4默认使用redis缓存session等信息(以优先支持负载均衡下的节点无状态横向扩展)。
  • TLS/SSL/数据加密: OpenSSL
  • 静态文件服务: da4qi4自身支持静态文件(包括前端缓存逻辑)。实际项目部署建议与nginx配合。由nginx提供更高性能、更安全的接入及提从静态文件服务。

注:

  1. 框架未绑定数据库访问方式。用户可使用 Oracle 官方 C++ Connector,或MySQL++,或 三、运行时外部配套系统提及的各类数据库连接器;
  2. 框架自身使用 redis 作为默认的(可跨进程的)SESSION支持。上层应用可选用框架的redis接口,也可以使用自己喜欢、 顺手 的redis C++客户端。

0.3 易用优于性能

使用C++开发,基于异步框架,目的就是为了有一个较好的原生性能起点,开发者不要过于费心性能。当然,性能也不能差,因为性能差必将影响产品的易用性)。 暂时仅与 Tomcat 做了一个比较。由于Tomcat似乎是“Per Connection Per Thread/每连接每线程”,所以这个对比会有些胜之不武;但考虑到Tomcat曾广泛应用于实际系统,所以和它的对比数据有利于表明da4qi4在性能上的可用性。

基准测试环境:

  • ubuntu 18.04
  • 4核心8线程 、8G内存
  • 测试工具: Jmeter
  • 测试工具和服务端运行于同一机器(显然会影响服务端性能,不过本次测试重点是做相对性的对比)
  • 后台无业务,不访问数据库,仅返回简短字符串(造成吞吐量严重不足)
  • 不走nginx等Web Server的反向代理

Tomcat 运行配置

  • JVM 1.8G 内存

  • 最大线程数:10000

  • 最大连接数:20000

  • 最大等待队列长度 200

    对 Tomcat不算熟,因此以上配置基本照着网上的相关测试指南设置,有不合理之处,望指正。

- 并发数 平均响应(ms) 响应时间中位数(ms) 99% 用户响应时间(ms) 最小响应(ms) 最大响应(ms) 错误率 吞吐量(s) 每秒接收字节(KB)
tomcat 1000 350 337 872 1 879 0 886.7 273
da4qi4 1000 1 1 20 0 24 0 1233 286.6

有性能测试经验的人,应该能知道表中“da4qi4”的平均响应时长等数据,出现1毫秒的情况,这基本是因当前测试数据 喂不饱 受测对象的表现。但如果把da4qi4“喂饱了”,则用来对比的tomcat会被“喂爆了”,二者相差太大,很难“安排”出一个平衡点。考虑到后面肯定要选择别的对比对象,所以就这样吧。

另,官网 www.d2school.com 一度以 1M带度、1核CPU、1G 内存的一台服务器作为运行环境(即:同时还运行MySQL、redis服务);后因线上编译太慢,做了有限的升级。

后续会给出与其他Web Server的更多对比。但总体上,da4qi4 的当前阶段开发,基本不会以极端性能提升作为目标。

0.4 简单胜过炫技

这点没什么好说的,一个C++程序员走上工作岗位后必须拥有的基本素养:用你的能力把系统写简单,而不是把系统写复杂以证明你的能力。把系统做简单够用。克制把系统做复杂的冲动。

0.5 生产第一,自嗨顺便

只图写个一个玩具自嗨(练手)的话,应该什么技术都用最新、酷、炫,甚至最难的,比如能模板元就模板元……但要用于生产,除了简单,还要稳定、便捷。所以基本上只要有一台Ubuntu 18.04或更高版本的服务器(国内云服务器提供商都可提供),就可以简单几行指令准备好da4qi4的开发及部署环境。详见:二、如何构建

一、快速了解

1.1 一个空转的Web Server

我们需要一个C++文件,假设名为“main.cpp”,内容如下:

#include "daqi/da4qi4.hpp"

using namespace da4qi4;

int main()
{
    auto svc = Server::Supply(4098);
    svc->Run();
}

不到10行代码,我们创建了一个空转的,似乎不干活的Web Server。

编译、运行,然后在浏览器地址栏输入:http://127.0.0.1:4098 ,而后回车,浏览器将显示一个页面,上面写着:

Not Found

小提示:代码中的“Supply(4098)”调用,如果不提供4098这个入参,那么Web Server将在HTTP默认的80端口监听,如果使用SSL,默认在443端口监听。

虽然说它“不干活”,但其实这个Web Server的运行表现合乎逻辑:我们没有为它指定任何操作绑定,所以对它的任何访问都返回“Not Found”(404)。

1.2 Hello World!

不管访问什么都回一句“Not Found”这令人沮丧。接下来实现这么一个功能:当访问网站的根路径时,它能答应一声:“Hello World!”。

1.2.1 针对指定URL的响应

这需要我们大代码中指示框架遇上访问网站根路径时,做出必要的响应。响应可以是函数指针、std::function、类方法或C++11引入的lambda,我们先来使用最后者:

#include "daqi/da4qi4.hpp"

using namespace da4qi4;

int main()
{
    auto svc = Server::Supply(4098);

    svc->AddHandler(_GET_, "/", [](Context ctx)
    {
        ctx->Res().ReplyOk("Hello World!");
        ctx->Pass();
    });

    svc->Run();
}

例中使用到的Server类的AddHandler()方法,并提供三个入参:

  1. 指定的HTTP访问方法: _GET_;

  2. 指定的访问URL: /,即根路径 ;

  3. 匿名的lambda表达式。

三个入参以及方法名合起来表达一个意思:如果用户以GET方法访问网站的根路径,框架就调用lambda 表达式以做出响应。

编译、运行。现在用浏览器访问 http://127.0.0.1:4098 ,将看到:

Hello World!

作为对比,下面给出同样功能使用自由函数的实现:

#include "daqi/da4qi4.hpp"

using namespace da4qi4;

void hello(Context ctx)
{
    ctx->Res().ReplyOk("Hello World!");
    ctx->Pass();     
}

int main()
{
    auto svc = Server::Supply(4098);

    svc->AddHandler(_GET_, "/",  hello); 
    svc->Run();
}

为节省代码篇幅,后续演示均使用lambda表达式来表达HTTP的响应操作。实际系统显然不可能将代码全塞在main()函数中,因此平实的自由函数会用得更多。不仅lambda不是必需,实际是连“class/类”都很少使用——这符号Web Server基本的要求:尽量不要带状态;自由函数相比类的成员函数(或称方法),更“天然的”不带状态。

1.2.2 返回HTML

以上代码返回给浏览器纯文本内容,接下来,应该来返回HTML格式的内容。出于演示目的,我们干了一件有“恶臭”的事:直接在代码中写HTML字符串。放心,后面很快会演示正常的做法:使用静态文件,或者基于网页模板文件来定制网页的页面内容;但现在,让我们来修改第11行代码调用ReplyOK()函数的入参,原来是“Hello World!”,现在将它改成一串HTML:

……
   ctx->Res().ReplyOk("<html><body><h1>Hello World!</h1></body></html>");
……

1.3 处理请求

接下来,我们希望请求和响应的内容都能够有点变化,并且二者的变化存在一定的匹配关系。具体是:在请求的URL中,加一个参数,假设是“name=Tom”,则我们希望后台能返回“Hello Tom!”。

这就需要用到“Request/请求”和“Response/响应”:

#include "daqi/da4qi4.hpp"

using namespace da4qi4;

int main()
{
    auto svc = Server::Supply(4098);

    svc->AddHandler(_GET_, "/", [](Context ctx)
    {
        std::string name = ctx->Req("name");
        std::string html = "<html><body><h1>Hello " + name + "!</h1></body></html>";
        ctx->Res().ReplyOk(html);
        ctx->Pass();
    });

    svc->Run();
}

编译、运行。通过浏览器访问 “http://127.0.0.1:4098/?name=Tom” ,将得到带有HTML格式控制的 “Hello Tom!”。

1.4 引入“Application”

Server代表一个Web 服务端,但同一个Web Server系统很可能可分成多个不同的人群。

举例:比如写一个在线商城,第一类用户,也是主要的用户,当然就是来商城在线购物的买家,第二类用户则是卖家和商城的管理员。这种区别,也可以称作是:一个服务端,多个应用。在大器框架中,应用以Application表达。

就当前而言,还不到演示一个Server上挂接多个Application的复杂案例,那我们为什么要开始介绍Application呢?Application才是负责应后台行为的主要实现者。在前面的例子中,虽然没有在代码中虽然只看到Server,但背后是由Server帮我们创建一个默认的 Application 对象,然后依靠该默认对象以实现演示中的相关功能。

现在我们要做的是:显式创建一个Application对象,并代替Server对象来实前面最后一个例子的功能。

#include "daqi/da4qi4.hpp"

using namespace da4qi4;

int main()
{
    auto svc = Server::Supply(4098);
    auto app = Application::Customize("web", "/", "./log");

    app->AddHandler(_GET_, "/", [](Context ctx)
    {
        std::string name = ctx->Req("name");
        std::string html 
             = "<html><body><h1>Hello " + name + "!</h1></body></html>";
        ctx->Res().ReplyOk(html);
        ctx->Pass();
    });

    svc->Mount(app);
    svc->Run();
}

发生的变化:使用Aplication类的静态成员函数,定制(Customize)了一个应用,例中命名为app;然后改用它来添加前端以GET方法访问网站根URL路径时的处理方法。最后在svc运行之前,需要先将该应用挂接(Mount)上去。

这段代码和前面没有显式引入Application的代码,功能一致,输出效果也一致。但为什么我们一定要引入Application呢?除了前述的,为将来一个Server对应多个Application做准备之外,从设计及运维上讲,还有一个目的:让Server和Application各背责任。 Application负责较为高层的逻辑,重点是具体的某类业务,而Server则负责服务器较基础的逻辑,重点是网络方面的功能 。下一小节将要讲到日志,正好是二者分工的一个典型体现。

1.5 运行日志

一个Web Server在运行时,当然容易遇到或产生各种问题。这时候后台能够输出、存储运行时的各种日志是大有必要的功能。

结合前面所说的Server与Application的分工。日志在归集上就被分成两大部分:服务日志和应用日志。

  • 服务层日志:记录底层网络、相关的周边运行支撑环境(缓存/Redis、数据库/MySQL)等基础设施的运行状态。

  • 应用层日志:记录具体应用的运行日志。

其中,相对底层的Server日志全局唯一,由框架自动创建;而应用层日志自然是每个应用对应一套日志。程序可以为服务层和应用层日志创建不同的日志策略。事实上,如果有多个应用,那自然可以为每个应用定制不同的日志策略。

在前面例子中,服务层日志对象已经存在,只是我们没有主动配置它,也没有主动使用它记录日志。而唯一的应用web_app则采用默认的日记策略:即没有日志。没错,应用允许不记录日志。

为了使用服务层日志,我们需要在程序启动后,服务还未创建时,就初始化服务层的日志对象,这样才有机会记录服务创建过程中的日志(比如最常见的,服务端口被占用的问题)。假设初始化日志这一步都失败,记录失败信息的人,肯定不能是日志对象,只能是我们熟悉的std::cerr或std::cout对象。

#include "daqi/da4qi4.hpp"

using namespace da4qi4;

int main()
{
    if (!log::InitServerLogger("/home/zhuangyan/Projects/CPP/daqi_demo/www/logs", log::Level::debug))
    {
        std::cerr << "Create server logger fail." << std::endl;
        return -1;
    }

    auto svc = Server::Supply(4098);
    log::Server()->info("准备web应用中……"); 

    auto app = Application::Customize("web", "/", "./log");

    app->AddHandler(_GET_, "/", [](Context ctx)
    {
        std::string name = ctx->Req("name");
        std::string html = "<html><body><h1>Hello " + name + "!</h1></body></html>";
        ctx->Res().ReplyOk(html);
        ctx->Pass();
    });

    svc->Mount(app);
    svc->Run();
}

小提示:为方便演示,上面代码暂时使用绝对路径以指定服务层日志文件的存储位置,实际项目通常以相对路径,或读取外部配置的方式以方便部署。

一旦“InitServerLogger()”调用成功,并且设置低于INFO的日志输出级别(例中为DEBUG级别,见该函数的第2个入参:log::Level::debug),框架中有关服务层的许多日志,就会打印到屏幕(控制台)上及相应的日志文件里。

下面是运行日志截图示例。

输入图片说明

当然,当程序运行在服务器上,它会被配置成在后台运行,没有界面,日志被重定向到文件。

1.6 HTML 模板

是时候解决在代码中直接写HTML的问题了。

用户最终看到的网页的内容,有一些在系统设计阶段就很清楚,有一些则必须等用户访问时才知道。比如前面的例子中,在设计时就清楚的有:页面字体格式,以及“Hello, _ _ _ _ !”;而需要在运行时用户访问后才能知道的,就是当中的下划线处所要填写的内容。

下面是适用于本例的,一个相当简单的的HTMl网页模板:

<!DOCTYPE html>
<html lang="zh">
<head>
    <title>首页</title>
    <meta content="text/html; charset=UTF-8">
</head>
<body>
    <h1>你好,{=name=}!</h1>
    <p>您正在使用的浏览器: {=_HEADER_("User-Agent")=}</p>
    <p>您正在通过该网址访问本站:{=_HEADER_("Host")=}</p>
</body>
</html>

“你好,”后面的特定格式{=name=},将会被程序的模板解析引擎识别,并填写上运行时的提供的name的值。

_HEADER_()是框架内置的函数,获得当前HTTP请求的报头数据项。在本例中无实际作用,仅用于演示一种常用的页面调试方法。

使用模板后,现在用于产生的网页内容的完整C++代码如下:

#include "daqi/da4qi4.hpp"

using namespace da4qi4;

int main()
{
    //网站根目录 (同样,我们暂使用绝对路径)
    std::string www_root = "/home/zhuangyan/Projects/CPP/daqi_demo/www/";

    //初始化服务层日志
    if (!log::InitServerLogger(www_root + "logs", log::Level::debug))
    {
        std::cerr << "Create server logger fail." << std::endl;
        return -1;
    }

    auto svc = Server::Supply(4098);
    log::Server()->info("准备web应用中……"); //纯粹是为了演示日志……

    auto app = Application::Customize("web", "/",
                                          www_root + "logs/", www_root + "static/",
                                          www_root + "view/", www_root + "upload/");

    //初始化web应用日志
    if (!app->Init(Application::ActualLogger::yes, log::Level::debug))
    {
        log::Server()->critical("Init application {} fail.", web_app->GetName()); 
        return -2;
    }

    //添加请求处理
    app->AddHandler(_GET_, "/", [](Context ctx)
    {
        std::string name = ctx->Req().GetUrlParameter("name");
        ctx->ModelData()["name"] = name;
        ctx->Render().Pass();
    });

    svc->Mount(app);
    svc->Run();
}

由于我们所写的模板文件正确地指定了相关编码,所以现在如果访问 http://127.0.0.1:4098?name=大器da4qi4 。将得到带有HTML格式的:

你好,大器da4qi4!

框架提供的模板引擎,不仅能替换数据,也支持基本的条件判断、循环、自定函数等功能,类似一门“脚本”。

小提示:大多数情况下,我们写的C++程序用以高性能地、从各种来源(数据库、缓存、文件、网络等)、以各种花样(同步、异步)获取数据、处理数据。而HTML模板引擎在C++程序中以解释的方式运行,因此正常的做法是不要让一个模板引擎干太复杂的,毕竟,在C++这种“彪形大汉”的语言面,它就是个小孩子。

最后,如果一个页面仅仅是修改一些样式,比如把某些字体从黑色改成红色,那么我们就不应该重启Web Server(更无需重新编译),实现对模板的“热加载”。为达成这一效果,需要在“svc->Run()”之前添加一行代码:

...
int main()
{ 
   ...

   svc->Mount(app);
   svc->EnableDetectTemplates(3); //3秒,实际部署时,建议设置为一个较大秒数,比如 15 * 60 
   svc->Run();
}

1.7 更多

1.7.1 框架更多集成功能

  1. cookie支持

  2. 前端(浏览器)缓存支持

  3. Redis 缓存支持

  4. Session 支持

  5. 静态文件

  6. 模板文件更新检测及热加载

  7. HTTP/HTTPS 客户端组件(已基于此实现微信扫码登录、阿里云短信的C++SDK,见下)

  8. POST响应支持

  9. 文件上传、下载

  10. 访问限流

  11. JSON

  12. 纯数据输出的API接口,与前端AJAX配合

  13. 框架全方式集成:(a) 基于源代码集成、(b) 基于动态库集成、(c) 基于静态库集成

  14. 常用编码转换(UTF-8、UCS、GBK、GB18030)

  15. ……

1.7.2 框架外围可供集成的工具

  1. 数据库访问

  2. 和nginx配合(实现负载均衡的快速横向扩展)

  3. 阿里短信云异步客户端

  4. 微信扫一扫登录异步客户端

  5. 基于OpenSSL的数据加密工具

  6. 常用字符串处理

  7. ……

二、如何构建

2.1 基于生产环境构建

大器 当前支持在Linux下环境编译。(因为我的服务端程序基本都在linux下,不过试验一下如何在Windows下编译。方便学习,但不推荐实用)

为方便构建,大器的相关构建工具及外部信赖库,与“阿里云”(“腾讯云”、“华为云”、“七牛云”等国内云计算商类似)的Ubuntu 服务器版本保持基本同步。

因此,如果你有一台2019年或更新的云服务器,那么在其上构建大器,则所需的软件、信赖库等,只要Ubuntu仓库中存在,均只需使用“apt”指令从云厂商为该版本的Ubuntu提供的软件仓库拉取即可。当前仅“iconv”库需要手动下载编译。

当前国内各云计算提供商,均提供 Ubuntu Server 版本为 18.04 LTS 版本。以下内容均以 Ubuntu 18.04 为例,考虑日常开发不会直接使用Server版,因此严格讲,以下内容均假设系统环境为 Ubuntu 18.04 桌面版。

小提示-服务器与开发机的区别:

因此也假设你的开发机使用的是Ubuntu 桌面版 18.04 LTS 版本。以下涉及apt指令时,以开发机(桌面版)为例,因为如有需要,均带着“sudo ”前缀。当在服务器(Ubuntu Server)上编译,并且你使用的是默认的root用户,只需去掉 “sudo”前缀即可。例如:

开发机: sudo apt install git

服务器: apt install git

2.2 准备编译工具

  1. 如果未安装或不知道有没有安装(以下简称为“准备”) GCC 编译器:
sudo apt install build-essential
  1. 准备 CMake构建套件,请:
sudo apt install cmake

2.3 准备第三方库

  1. 准备 boost 开发库:
sudo apt install libboost-dev libboost-filesystem libboost-system

小提示-安装全部boost库:

boost中需要编译的库,大器只用到上述的“filesytem”和“system”。如果你想一次性安装所有boost库,可以使用:sudo apt install libboost-dev libboost-all-dev

  1. 准备openssl及其开发库:
sudo apt install openssl libssl-dev
  1. 准备 libiconv 库

我们使用汉字,而汉字有多种编码方案,因此,汉字的编码转换,是开发包括Web应用在内各种软件系统的常见需求。大器框架通过集成iconv库用以实现支持多国语言多种编码的转换功能。

先下载:https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.16.tar.gz

在Ubuntu图形界面中,双击该.gz文件,再点击其内.tar文件,解压后得到 “libiconv-1.16”文件夹。在终端进入该文件夹,依次输入以下三行,完成安装:

./configure --prefix=/usr/local
make
sudo make install
  1. 最后,确保生效所安装的动态库在系统中能被找到:
sudo ldconfig

2.4 下载大器源代码

通常你应该安装 git 工具,如果没有或不确定,请打开终端(Ctrl + Alt + T),按如下指令安装。

sudo apt install git 

然后在本地新建一文件夹,假设命名为 daqi,打开终端进入该目录,从github克隆代码:

git clone https://github.com/d2school/da4qi4.git

或者从国内的gitee克隆代码(速度比较快):

git  clone  https://gitee.com/zhuangyan-stone/da4qi4_public.git

最终,你将在前述的“daqi”目录下,得到一个子目录“da4qi4”(也可能是别的,看git源)。大器项目的代码位于后者内,其内你应该能看到“src”、“include”等多个子目录。

如有余力,建议在以上两个网站均为本开源项目打个星 。

2.5 编译“大器”库

重要:以下假设大器源代码位于“daqi/da4qi4”目录下。

  1. 准备构建目录

请在“daqi”之下(和“da4qi4”平级)的位置,新建一目录,名为“build”:

mkdir build

进入该当目录:

cd build
  1. 执行CMake
cmake -D_DAQI_TARGET_TYPE_=SHARED_LIB -DCMAKE_BUILD_TYPE=Release ../da4qi4/

将生成目标为“发行版(Release)”的大器“动态库(SHARED_LIB)”。

  • 如果希望生成调试版本,请将“Release”替换为“Debug”;
  • 如果希望生成静态库版本,请将“SHARED_LIB”替换为“STATIC_LIB”;
  • 更多编译目标设置,请到本项目官网“www.d2school.com”

一切正常的看,将看到终端上输出“Generating done”等字样。其中更多内容中,包含有boost库的版本号、库所在路径,以及一行“~BUILD DAQI AS SHARED LIB~”字样以指示大器的编译形式(SHARED LIB)。

  1. 开始编译
make

小提示:并行编译

如果你的电脑拥有多核CPU,并且内存足够大(至少8G),可以按如下方式并行编译(其中 -j 后面的数字,指明并行编译的核数,以下以四核数例):

make -j4

完成make之后,以上过程将在build目录内,得到“libda4qi4.so”;

如果是调试版,将得到 “libda4qi4_d.so”。如果是静态库,则扩展为“.a”。

2.6 在你的项目中使用 da4qi4库

现在,你可以使用你熟悉IDE(Code::Blocks、Qt Creator、CodeLite等)中,构建你的项目,然后以类型使用其它开发库的方式,添加大器的库文件(就是前一步构建所得的.so或.a文件),及大器的头文件。

  1. da4qi4库文件。 即前面编译大器库得到的库文件,如“libda4qi4.so”或“libda4qi4.a”,“libda4qi4_d.so”、“libda4qi4_d.a”等文件。
  2. da4qi4库依赖的文件。 在Linux下,它们是 pthread、ssl、crypto、boost_filesystem、boost_system
  3. da4qi4头文件:“大器项目目录”、“大器项目目录/include”及“大器项目目录/nlohmann_json/include/”

下面以CMake的CMakefiles.txt为例:

cmake_minimum_required(VERSION 3.5)

project(hello_daqi LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wall")

# 此处设置大器项目目录
set(_DAQI_PROJECT_PATH_ "你的大器项目所在目录")
# 此处设置大器项目编译后得到的 .so 文件所在目录
set(_DAQI_LIBRARY_PATH_ "你的大器项目动态库所在目录")

include_directories(${_DAQI_PROJECT_PATH_})
include_directories(${_DAQI_PROJECT_PATH_}/include)
include_directories(${_DAQI_PROJECT_PATH_}/nlohmann_json/include/)

find_package(Boost 1.65.0 REQUIRED COMPONENTS filesystem system)
link_directories(${_DAQI_LIBRARY_PATH_})

link_libraries(da4qi4)

link_libraries(pthread)
link_libraries(ssl)
link_libraries(crypto)
link_libraries(boost_filesystem)
link_libraries(boost_system)

add_executable(hello_daqi main.cpp)

现在,你可以从之前“1.1 一个空转的Web Server”重新看起。

三、运行时外部配套系统

3.1 运行时依赖说明

一个Web系统常用到缓存系统和数据库系统。大器框架对二者依赖情况如下:

  • 完全不依赖数据库;
  • 简单例子不依赖缓存系统,但一旦需要用到Web 系统常见的“会话/SESSION”功能,则需要依赖redis缓存库。

3.2 Redis的安装

显然,这已经不是本开源项目的自己的说明内容。不过,反正在Ubuntu Linux下安装Redis就一行话:

sudo apt install redis-server

这不仅会安装redis服务,而且会顺便在本机redis的命令行客户端,可以如下运行:

redis-cli
  • 有关如何在你写的大器Web Server中实现SESSION,请参看本项目官网www.d2school.com 相关(免费视频)课程;
  • 有关Redis的学习,请关注www.d2school.com 课程。

3.3 数据库

  • 可以使用 mysql 官方的 MySQL C++ Connector;
  • 新人强烈推荐: 相对传统的C++封装 : MySQL++ (注:欢迎关注《白话 C++》下册,有详细的 MySQL 数据库及 MySQL++使用的章节;
  • 新人推荐: CppDB
  • github上,搜索 “MySQL C++”,你将找到大量国内或国外的MySQL C++连接库;
  • 有经验的C++程序员推荐:sqlpp11

更多课程(视频课程、文字课程),请到 第2学堂查看。 谢谢。

Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2018 zhuangyan-stone Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

简介

C++ 高性能 Web Server 快速开发框架 展开 收起
C++
Apache-2.0
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
C++
1
https://gitee.com/w-s-j/da4qi4_public.git
git@gitee.com:w-s-j/da4qi4_public.git
w-s-j
da4qi4_public
da4qi4_public
master

搜索帮助