摘录至 一文读懂 HTTP/2 特性
参考 HTTP/2 幕后原理

仅做个人学习记录用途。

HTTP/2 是 HTTP 协议自 1999 年 HTTP 1.1 发布后的首个更新,主要基于 SPDY 协议。由互联网工程任务组(IETF)的 Hypertext Transfer Protocol Bis(httpbis)工作小组进行开发。该组织于2014年12月将HTTP/2标准提议递交至IESG进行讨论,于2015年2月17日被批准。HTTP/2标准于2015年5月以RFC 7540正式发表。

二进制分帧

帧:HTTP/2 数据通信的最小单位消息:指 HTTP/2 中逻辑上的 HTTP 消息。例如请求和响应等,消息由一个或多个帧组成。

流:存在于连接中的一个虚拟通道。流可以承载双向消息,每个流都有一个唯一的整数ID。

HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x 的文本格式,二进制协议解析起来更高效。 HTTP / 1 的请求和响应报文,都是由起始行,首部和实体正文(可选)组成,各部分之间以文本换行符分隔。HTTP/2 将请求和响应数据分割为更小的帧,并且它们采用二进制编码。

HTTP/2 中,同域名下所有通信都在单个连接上完成,该连接可以承载任意数量的双向数据流。每个数据流都以消息的形式发送,而消息又由一个或多个帧组成。多个帧之间可以乱序发送,根据帧首部的流标识可以重新组装。

多路复用

多路复用,代替原来的序列和阻塞机制。所有就是请求的都是通过一个 TCP连接并发完成。

在 HTTP/2 中,有了二进制分帧之后,HTTP /2 不再依赖 TCP 链接去实现多流并行了,在 HTTP/2中:

同域名下所有通信都在单个连接上完成。
单个连接可以承载任意数量的双向数据流。
数据流以消息的形式发送,而消息又由一个或多个帧组成,多个帧之间可以乱序发送,因为根据帧首部的流标识可以重新组装。
这一特性,使性能有了极大提升:

同个域名只需要占用一个 TCP 连接,消除了因多个 TCP 连接而带来的延时和内存消耗。
单个连接上可以并行交错的请求和响应,之间互不干扰。
在HTTP/2中,每个请求都可以带一个31bit的优先值,0表示最高优先级, 数值越大优先级越低。有了这个优先值,客户端和服务器就可以在处理不同的流时采取不同的策略,以最优的方式发送流、消息和帧。

服务器推送

服务端可以在发送页面HTML时主动推送其它资源,而不用等到浏览器解析到相应位置,发起请求再响应。例如服务端可以主动把JS和CSS文件推送给客户端,而不需要客户端解析HTML时再发送这些请求。

服务端可以主动推送,客户端也有权利选择是否接收。如果服务端推送的资源已经被浏览器缓存过,浏览器可以通过发送RST_STREAM帧来拒收。主动推送也遵守同源策略,服务器不会随便推送第三方资源给客户端。

头部压缩

转 std::string

CUtils::UnicodeToAscii(wstring(strDeviceAddr)).c_str()

创建表

CREATE TABLE IF NOT EXISTS iotbackend.tableName ()

如果想查看这些表的结构

select * from sqlite_master where type="table";

如果只想查看具体一张表的表结构,比如查看emperors表,命令为:

select * from sqlite_master where type="table" and name="emperors";

创建表

默认时间字段

注意,如果使用了 int64 的整形,需要明确指定长度。

CREATE TABLE IF NOT EXISTS main.tableName (
f_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
f_datetime TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,
f_id_name INTEGER(8) NOT NULL);

create table log(
content varchar(256),
logtime TIMESTAMP default (datetime('now', 'localtime'))
)
datetime(CURRENT_TIMESTAMP,'localtime')

CREATE TABLE IF NOT EXISTS main.tableName (f_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, f_datetime TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL, f_id_name INTEGER(8) NOT NULL);

添加字段

ALTER TABLE 表名 ADD COLUMN 列名 数据类型 

eg: ALTER TABLE new_table ADD COLUMN sex Text;

修改表名称

ALTER TABLE 旧表名 RENAME TO 新表名 

eg: ALTER TABLE or_sql_table RENAME TO new_table;

查询表结构

PRAGMA TABLE_INFO (表名)

eg: PRAGMA TABLE_INFO (new_table);

删除表

DROP TABLE table_name;

gRPC主要有4种请求/响应模式,分别是:

(1) 简单模式(Simple RPC)

这种模式最为传统,即客户端发起一次请求,服务端响应一个数据,这和大家平时熟悉的RPC没有什么大的区别,所以不再详细介绍。

(2) 服务端数据流模式(Server-side streaming RPC)

这种模式是客户端发起一次请求,服务端返回一段连续的数据流。典型的例子是客户端向服务端发送一个股票代码,服务端就把该股票的实时数据源源不断的返回给客户端。

(3) 客户端数据流模式(Client-side streaming RPC)

与服务端数据流模式相反,这次是客户端源源不断的向服务端发送数据流,而在发送结束后,由服务端返回一个响应。典型的例子是物联网终端向服务器报送数据。

(4) 双向数据流模式(Bidirectional streaming RPC)

顾名思义,这是客户端和服务端都可以向对方发送数据流,这个时候双方的数据可以同时互相发送,也就是可以实现实时交互。典型的例子是聊天机器人。

use c++

windows

To prepare for cmake + Microsoft Visual C++ compiler build

Install Visual Studio 2015 or 2017 (Visual C++ compiler will be used).
Install Git.
Install CMake.
Install Active State Perl (choco install activeperl) - required by boringssl
Install Go (choco install golang) - required by boringssl
Install yasm and add it to PATH (choco install yasm) - required by boringssl
(Optional) Install Ninja (choco install ninja)

下载指定版本
gRPC

git clone --recursive -b v1.23.0 https://github.com/grpc/grpc

// 如果有子模块失败,使用下面命令更新
git submodule update --init --recursive

// 编译软件

md .build
cd .build
cmake .. -G "Visual Studio 14 2015"
cmake --build . --config Release

生成代码

route_guide.pb.h - 消息类的头文件
route_guide.pb.cc - 其中包含消息类的实现
route_guide.grpc.pb.h - 服务类的头文件
route_guide.grpc.pb.cc - 其中包含服务类的实现

"protoc.exe" -I="D:\project\rpcDemo\rpcDemo" --grpc_out="D:\project\rpcDemo\rpcDemo" --plugin=protoc-gen-grpc="grpc_cpp_plugin.exe" "D:\project\rpcDemo\rpcDemo\\rpc_api.proto"

"D:\\project\\grpc\\.build\\third_party\\protobuf\\Release\\protoc.exe" -I="D:\project\rpcDemo\rpcDemo" --cpp_out="D:\project\rpcDemo\rpcDemo" "D:\project\rpcDemo\rpcDemo\rpc_api.proto"


protoc -I ../../protos --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` ../../protos/route_guide.proto

protoc –grpc_out=. –plugin=protoc-gen-grpc=grpc_cpp_plugin.exe ./rpc_api.proto

protoc -I ../../protos --cpp_out=. ../../protos/route_guide.proto

rpcClient

// for rpc client
#include <grpcpp/grpcpp.h>

using grpc::Channel;
using grpc::ClientContext;


class rpcClient {
public:
rpcClient(std::shared_ptr<Channel> channel)
: stub_(apiService::apiService::NewStub(channel)) {}

// Assembles the client's payload, sends it and presents the response back
// from the server.
std::string SendMsg(const std::string& msg) {
// Data we are sending to the server.
apiService::Request request;
request.set_value(msg);

// Container for the data we expect from the server.
apiService::Response reply;

// Context for the client. It could be used to convey extra information to
// the server and/or tweak certain RPC behaviors.
ClientContext context;

// The actual RPC.
Status status = stub_->apiTrans(&context, request, &reply);

// Act upon its status.
if (status.ok()) {
return reply.value();
}
else {
std::cout << status.error_code() << ": " << status.error_message()
<< std::endl;
return "";
}
}

private:
std::unique_ptr<apiService::apiService::Stub> stub_;
};

void rpcClient()
{
rpcClient greeter(grpc::CreateChannel("localhost:53061", grpc::InsecureChannelCredentials()));
std::string user("world");
std::string reply = greeter.SendMsg(user);
std::cout << "Greeter received: " << reply << std::endl;
}

问题

warning C4003: not enough actual parameters for macro ‘min’
包含rpc的头文件要在windows前面

包含库文件

libprotobufd.lib
gpr.lib
grpc.lib
grpc++.lib
Ws2_32.lib
zlibstaticd.lib
caresd.lib
address_sortingd.lib

#include <grpc/grpc.h>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpc++/security/server_credentials.h>
#undef max
#undef min
#include "rpc_api.grpc.pb.h"
#include "rpc_api.pb.h"

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;

“Please compile grpc with _WIN32_WINNT of at least 0x600 (aka Windows Vista)”

需要在项目设置里面定义 _WIN32_WINNT=0x600 宏

讲了几大定律,需要有切身的体会才能更好的领悟。推荐阅读

20190831_064644.png

DELETE FROM table WHERE search_condition;


DELETE FROM table
WHERE search_condition
ORDER BY criteria
LIMIT row_count OFFSET offset;

CityHash算法的开发是受到了 MurmurHash的启发
为了满足大数量的需求,减少碰撞,我们一般需要给出一个32位,64位或者128位的哈希,Google发布了一个叫做CityHash的方法,
能比较快的生成一个32位,64位或者128位的字符串签名,效率在64位cpu上得到了特殊优化,在工业级应用中可以使用该哈希算法,代码公布在google code上。

总体而言,CityHash64 与 CityHash128 是解决经典问题的全新算法

https://github.com/google/cityhash

murmurhash
属于非加密型hash算法

MurmurHash算法:高运算性能,低碰撞率,由Austin Appleby创建于2008年,现已应用到Hadoop、libstdc++、nginx、libmemcached等开源系统。
2011年Appleby被Google雇佣,随后Google推出其变种的CityHash算法。

Murmur is a family of good general purpose hashing functions, suitable for non-cryptographic usage. As stated by Austin Appleby, MurmurHash provides the following benefits:

simple (in term of number of generated assembly instructions).
good distribution (passing chi-squared tests for practically all keysets & bucket sizes.
good avalanche behavior (max bias of 0.5%).
good collision resistance (passes Bob Jenkin’s frog.c torture-test. No collisions possible for 4-byte keys, no small (1- to 7-bit) differentials).
great performance on Intel/AMD hardware, good tradeoff between hash quality and CPU consumption.

MySQL 的各种 text 字段有不同的限制, 要手动区分 small text, middle text, large text… Pg 没有这个限制, text 能支持各种大小.
不少人应该遇到过 MySQL 里需要 utf8mb4 才能显示 emoji 的坑, Pg 就没这个坑.

PostgreSQL 的稳定性极强, Innodb 等引擎在崩溃、断电之类的灾难场景下抗打击能力有了长足进步,然而很多 MySQL 用户都遇到过Server级的数据库丢失的场景——mysql系统库是MyISAM的,相比之下,PG数据库这方面要好一些。

PG 多年来在 GIS 领域处于优势地位,因为它有丰富的几何类型,实际上不止几何类型,PG有大量字典、数组、bitmap 等数据类型,相比之下mysql就差很多,instagram就是因为PG的空间数据库扩展POSTGIS远远强于MYSQL的my spatial而采用PGSQL的。

它可以存储 array 和 json, 可以在 array 和 json 上建索引, 甚至还能用表达式索引. 为了实现文档数据库的功能, 设计了 jsonb 的存储结构. 有人会说为什么不用 Mongodb 的 BSON 呢? Pg 的开发团队曾经考虑过, 但是他们看到 BSON 把 [“a”, “b”, “c”] 存成 {0: “a”, 1: “b”, 2: “c”} 的时候就决定要重新做一个 jsonb 了… 现在 jsonb 的性能已经优于 BSON.

它有地理信息处理扩展 (GIS 扩展不仅限于真实世界, 游戏里的地形什么的也可以), 可以用 Pg 搭寻路服务器和地图服务器:
PostGIS — Spatial and Geographic Objects for PostgreSQL
http://postgis.net/

它自带全文搜索功能 (不用费劲再装一个 elasticsearch 咯):Full text search in milliseconds with PostgreSQL 不过一些语言相关的支持还不太完善, 有个 bamboo 插件用调教过的 mecab 做中文分词, 如果要求比较高, 还是自己分了词再存到 tsvector 比较好.

它支持 trigram 索引.trigram 索引可以帮助改进全文搜索的结果: PostgreSQL: Documentation: 9.3: pg_trgmtrigram 还可以实现高效的正则搜索 (原理参考 https://swtch.com/~rsc/regexp/regexp4.html )

MySQL 处理树状回复的设计会很复杂, 而且需要写很多代码, 而 Pg 可以高效处理树结构:Scaling Threaded Comments on Django at Disqushttp://www.slideshare.net/quipo/trees-in-the-database-advanced-data-structures

它可以把 70 种外部数据源 (包括 Mysql, Oracle, CSV, hadoop …) 当成自己数据库中的表来查询:
Foreign data wrappers

20190828_101925.png 20190828_101943.png 20190828_102009.png 20190828_102020.png 20190828_102038.png

  • 多使用显式事务。
  • 选择合适的PageSize,详细请看SQLite 知识摘要 — 存储。
  • 操作频繁 ,大量小记录(不使用显式事务),建议使用JournalMode :WAL 搭配 Synchronous: OFF。
  • 操作少 ,数据量大,使用默认的方式就好。看数据是否重要,可搭配 :JournalMode : TRUNCATE | PERSIST 和 Synchronous: OFF。
  • 数据量大,但是数据可以重建,建议使用JournalMode :Memory ,搭配 Synchronous: OFF。HttpURLCache 就属于这种。