mbedtls握手耗时问题
1.表面现象:在NVR上添加mini_httpd作为web服务器https出现访问慢问题,一条请求几乎五六百毫秒,一个页面十几个甚至几十个请求那就更卡了,再深入一点抓个包看看可以发现TLS握手过程中报错如图,Alert(Level:Fatal,Description Unknown)这个报错就是网上的( Description Unknown 46 )报错原因是证书不是CA证书浏览器上面直接就有不安全字样,如果源码加打印,如图二看到返回0x7780错误值,由于服务端选择不认证证书选项 所以第二次请求才会请求成功,一条命令两次请求耗时加长。(首先由于是局域网访问直接访问nvr 的IP地址,所以这个证书问题避免不了,为了解决这个问题也在阿里云申请了免费的证书,会发现证书是跟域名绑定的,又申请一个域名,申请阿里云ssl证书具体流程还是看下一篇文章)
TLS认证问题抓包(图1)
mbedtls握手返回值(图2)
申请了阿里云SSL证书后(几天过去了!!!),浏览器通过域名去访问nvr的web端不会报证书错误,再抓包就不会出现证书报错问题了,这时候发现一个请求耗时还是很久并没有大的改观,mbedtls源码中会设置recv和send的回调,mbedtls_ssl_set_bio(ssl,net,mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);在握手阶段的交互就是通过这两个接口去发送接受的,在recv和send接口加时间打印发现,延时主要是在浏览器给我们发送证书验证后的finished的消息时候延时高,延时大概200毫秒左右,所以一个请求下来平均也要三四百毫秒。到了这里也是百思不得其解,也找了最新的github上mbedtls代码去编译demo,发现demo的握手延时跟我们差不多,那简直没话说了,官方demo都这样那还咋。但是对比nginx的ssl差的不是一星半点,nginx一个请求差不多七八十毫秒,有的几毫秒(没有开cahce时候哈),快的不得了,又去看了一堆nginx优化一大堆(什么false start(抢占技术),什么ticket,缓存…)。
原来Tcp默认有一个nagle算法导致需要MSS缓冲收满或者超时才会发包,而握手阶段可能只有几个字节,所以只需要添加如下代码就好了
int flag = 1;
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(flag));
对TCP_NODELAY 解释很深刻的文章链接。
文章写的很粗糙很多细节都可以具体的写好几篇续集,写出来就是为了让遇到同样问题人能看到答案,毕竟对mini_httpd的web服务端优化介绍很少。