[步入rust]从零开始进入Warp-初步接触

简介

warp是一个异步IO构建的Web框架,超级易于使用和简洁。并且由于其作者也是开发了hyper开发者,因此warp在Rust社区中有不错的热度。

并且由于独特的提供了其他Rust Web框架没有的Filter系统,所以以下组件开箱可用:

  • Path routing and parameter extraction / 路径路由及参数析出
  • Header requirements and extraction / Header参数析出
  • Query string deserialization / Query字符串反序列化
  • JSON and Form bodies / JSON和表单
  • Multipart form data / Multipart表单
  • Static Files and Directories / 静态文件和路径映射
  • Websockets
  • Access logging / 请求日志
  • Etc

底层的如下组件由hyper提供:

  • HTTP/1
  • HTTP/2
  • Asynchronous / 异步
  • One of the fastest HTTP implementations / 最快的HTTP实现之一
  • Tested and correct / 代码测试

GitLab CI使用Googletest自动化单元测试Qt代码

GoogleTest简介

GTest框架谷歌推出的一款C++单元测试框架,基于BSD3协议开源。因为是C++,所以基本上兼容所有系统。

QT项目集成GTest

QT Creator自带的Test集成插件可以快速帮助集成QTest或者GTest,虽然QTest是QT自带的测试框架,但是我还是更喜欢使用纯C++的东西。

新建项目->其他项目->Auto Test Project->配置项目TestCase TestSuit->选择GTest根目录

这就是一个完整可以运行的项目了,运行可以看见测试结果。

需要添加新的测试用例可以通过新建测试用例进行测试

TEST(TestSuit,TestCase){
    // do some test
}

根据自己项目的需求include被测项目header和cpp文件,这样可以将测试代码和要测试的代码一起编译导出。

当然如果被测项目是一个库的话,也是可以使用链接动态库的方式链接,但是这样就无法从单元测试结果获取测试代码覆盖率和分支覆盖率等信息。

如果需要那些信息的话还是建议和单元测试一起编译运行。

QT使用Breakpad

在c++开发中,很容易出现程序Crash而不出现任何提示的情况,尤其是在使用原生c++开发的情况,如果用了QT之类的框架还可能会输出一点点线索(也可能没有),在引入dump之前,我们都是用断点的方式debug,但是一旦发布出去,那就只能打印整个流程的所有log,来“云”调试。

所以为了解决收集和调试发布之后的程序,需要收集程序崩溃之后的信息,微软在其Windows平台上提供了minidump,需要引用WinDbg的库,注册handler也可以生成,但是这一套方案不是特别好用,而且也不能跨平台,所以Breakpad是比较好的第二方案。

Breakpad

Breakpad是谷歌开源的一个跨平台崩溃处理框架,内含崩溃转储、上报、分析一套工作流程框架。

主要的工作流程为:client以library的方式嵌入自己的程序,并设置handler,将会在程序崩溃时将会把一系列的线程列表、调用堆栈和一些系统信息写入minidump文件,再使用dump_syms将编译器生成的调试信息文件生成符号文件,最好在使用minidump_walker生成可以阅读的stack trace。

通过Homebridge使用Siri控制米家设备

去年用着米6为了补充室内灯光,就买了米家台灯,可以用小爱同学控制就很方便。然而后来换了苹果全家桶,Siri只认Homekit套件就有点难受,每次只好使用app去打开关闭,虽然在负一屏上可以放米家的组件,但是那东西经常的没反应,最后还是得去app里关台灯。

最近偶然发现有如Homebridge和Home Assistant的神器,可以让其他的智能家居套上一层皮摇身一变成为HomeKit组件。

安装Homebridge

当作中枢的Homebridge当然需要长时间运行,所以需要安装到家里一个长期运行的服务器上,当然只要是台电脑都行,比如树莓派什么的。

C++下实现机制的反射「2」——升级自省功能

上一篇「part1」中,实现了一个能够存储类的成员变量的结构,使用父类Base中的set_field方法,将派生类的成员变量映射进map中,所以我们只需要在Base类中编写一堆方法就能直接调用派生类的成员变量。

例如:

  • 导出成JSON格式数据
string to_json()
{
    string json = "{";
    for(auto i = m_table.begin(); i != m_table.end();)
    {
        json.append("\"");
        json.append(i->first);
        json.append("\":");
        switch(i->second.first)
        {
            case INT_TYPE:
                json.append(to_string(*static_cast<int*>(i->second.second)));
                break;
            case DOUBLE_TYPE:
                json.append(to_string(*static_cast<double*>(i->second.second)));
                break;
            case STRING_TYPE:
                json.append("\"");
                json.append(*static_cast<string*>(i->second.second));
                json.append("\"");
                break;
        }
        if(++i != m_table.end())
        {
            json.append(",");
        }
    }
    json.append("}");
    return json;
}

由于保存指针的类型是void *,所以在使用的时候都需要对其使用static_cast转化一下,使用强制转换也是可以的,然而因为指针所以是比较危险的操作,推荐还是用cast转化指针类型,才能正确的获取值。就这样不需要每个类都要重写一个方法,就能很愉快的节省时间,如果是QT框架的话还可以直接转化成QJsonObject更方便。

C++下实现机制的反射「1」——自省

反射(Reflection)机制

是指计算机程序在运行时(runtime)可以访问、检测和修改它本身状态或行为的一种能力。wiki

在其他语言中都有大量的应用,尤其是Java中反射与注解配合使用可以大大的减少工作量,降低重复代码,也能使程序更容易维护。现代Java框架中已经离不开反射与注解了。

目标

最近在公司的QT项目中需要大量的使用数据库,虽然QT提供了非常方便的数据库连接驱动与API,但是并没有更方便的ORM功能,只能拼写Sql语句之后运行,再从结果中手动处理得到对象。

虽然这么做并没有什么问题,但是问题是当一个软件设计到一定程度,例如出现了N个需要存储的对象,如果按照Model,DAO,Service,Controller的MVC设计思路,每一个Model都需要手动为其写insert,update,delete的函数。到最后,同样功能的sql语句可能会写十几遍,所以需要设计一套能应对此类情况的框架。

所以,我们就要在C++环境下设计与实现反射机制以及ORM系统。

生产者消费者模型下的爬虫|Web Crawler with Producer-consumer Pattern

提升爬虫效率

提升爬虫的抓取效率无非优化爬虫与服务器的链接速度和效率。最为简单的方式就是“加钱”,使用更大带宽的网络,和更高的并发。

所以很多情况下就可以使用多线程或者分布式的爬虫方案。然而在使用这些模式的爬虫情况下可能会出现另一些影响爬虫效率的因素:入库。

爬虫数据入库

单机情况下爬到的东西一般直接存到本地就行了,直接扔到一个文件内或者数据库内就行。

然而分布式情况下如果爬虫生产的数据存入统一的数据库,每次的存取就会进行一次事务,如果出现失败等情况还需要在爬虫中对这些错误进行处理,不然爬虫就会直接死掉。

爬虫与数据库之间的链接状况也会影响当前的爬虫进程,爬虫无法在数据库入库之前进行下一次抓取。

肯定有人会说:“先全部存到本地就好了啊,爬完再统一存进去。”确实这是一个减轻代码量的“好”方法。但是如果是一个长期项目,整理数据就不是那么的轻松了。

因此选择一个更生产者消费者模式能够更好的提高爬虫的效率。