写点什么

HTTP/2 探索第二篇——工具及应用

  • 2019-08-22
  • 本文字数:8569 字

    阅读完需:约 28 分钟

HTTP/2探索第二篇——工具及应用

目录结构:

HTTP/2 环境搭建 Step by step

wireshark 使用

fiddler 使用(会持续更新)

nginx 的简单配置

h2o 服务器及其 Server Push 策略思想简介 —— h2o 实现的可感知缓存的 Server Push,我们借用终端的力量应该能实现的更好

curl —— 涉及到 HTTP2 的调试

nghttp —— 一个 HTTP2 客户端请求工具,可以显示出请求的 Frame

nghttpd —— 一个 HTTP2 服务器搭建工具,可以搭建可 Server Push 的服务器

软件安装

一、证书 —— 自签发证书和 Lets Encrypt 证书申请

二、基本工具

三、服务器准备

四、开发准备

SSL/TLS 部分小贴士

活用证书提高性能

HSTS 和 CSP 提高安全

系列文章

Reference

HTTP/2 环境搭建 Step by step

本文需要安装的软件为(Mac 用户请使用 homebrew 来安装,括号里都是 Mac 的安装方式)


curl (brew install nghttp2 —with-nghttp2)


wget https: //curl .haxx.se/download/curl-7.48.0.tar.gz


tar xvf curl-7.48.0.tar.gz && cd curl-7.48.0


然后输入以下命令,exit 一次再进入然后版本是 7.48 就成功鸟:


  $ ./configure --with-nghttp2=/usr/local --with-ssl  $ make  $ sudo make install  $ ldconfig  $ usr/local/bin/curl -V
复制代码


Linux 安装


nghttp2 (brew install nghttp2)


安装网址


sudo apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config \zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \libjemalloc-dev cython python3-dev python-setuptools
复制代码


上面是安装依赖,之后就可以编译了:


$ autoreconf -i$ automake$ autoconf$ ./configure$ make$ sudo make installnginx (brew install nginx —devel)
复制代码


增加以下两行,其中 $codename 自行去该网站查询,比如 Ubuntu 14.04 是 trusty;


  deb http://nginx.org/packages/mainline/ubuntu/ $codename nginx  deb-src http://nginx.org/packages/mainline/ubuntu/ $codename nginx
复制代码


Linux 安装


vim 到/etc/apt/sources.list


然后 sudo apt-get update && sudo apt-get install nginx 就可以装最新支持 HTTP2 的 nginx 啦;


apache (brew install httpd24 —with-http2)[本文重点讲解 nginx]


Linux 安装

一、证书

自签发


打开提供的 Demo 文件,terminal 打开/keys 路径,输入./ca.sh http2test .com,也可以生成其他域名或泛域名(*.xx.com)。注意:也可以不用生成证书,直接使用 keys 文件下提供的 http2test.com 证书;

Let’s Encrypt

打开 Let’s Encrypt 的官网,这里讲解如果已经启动 nginx 的情况下,如何签发证书。


步骤:


首先需要把代码克隆下来:git clone https: //github. com/letsencrypt/letsencrypt && cd letsencrypt


然后./letsencrypt-auto --help 会执行一些初始化工作,并且显示支持的命令;


比如我的 web 目录在~/www 下,此步骤需要已搭建好服务器,并且可以通过 example.com 访问~/www 里的内容,如果是动态网站,需要在 nginx 层设置一个映射,将/.well-known/acme-challenge 映射到刚设置好的目录,也就是~/www。


  location /.well-known/acme-challenge {      root /home/$username/www;  }
复制代码


(需要 nginx 已经装好,没装好的完成下面的 nginx 部分后再回来设置)那么./letsencrypt-auto certonly --webroot -w ~/www -d example. com,example.com 是你希望申请证书的域名,然后证书下发成功。


然后在 nginx 中设置证书信息


  ssl_certificate /etc/letsencrypt/live/$example.com/fullchain.pem;  ssl_certificate_key /etc/letsencrypt/live/$example.com/privkey.pem;
复制代码


然后 sudo nginx -t && sudo nginx -s reload 就可以看到啦

二、基本工具

curl

curl 的基本用法是:


curl -v -o /dev/null --http2 http://nghttp2.org
复制代码


这里输入的是 HTTP 而不是 HTTPS 是因为,这里会采用 HTTP2 的 ClearText 模式,使用 101 改变协议协商升级为 HTTP2 协议。


Connected to nghttp2.org (106.186.112.116) port 80 (#0)> GET / HTTP/1.1> Host: nghttp2.org> User-Agent: curl/7.48.0> Accept: */*> Connection: Upgrade, HTTP2-Settings> Upgrade: h2c> HTTP2-Settings: AAMAAABkAAQAAP__>< HTTP/1.1 101 Switching Protocols< Connection: Upgrade< Upgrade: h2c* Received 101* Using HTTP2, server supports multi-use* Connection state changed (HTTP/2 confirmed)* TCP_NODELAY set* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=21* Connection state changed (MAX_CONCURRENT_STREAMS updated)!< HTTP/2.0 200< date:Sun, 10 Apr 2016 16:52:43 GMT< content-type:text/html< content-length:6646< last-modified:Sun, 03 Apr 2016 06:53:14 GMT< etag:"5700bdda-19f6"< link:</stylesheets/screen.css>; rel=preload; as=stylesheet< accept-ranges:bytes< x-backend-header-rtt:0.000625< server:nghttpx nghttp2/1.10.0-DEV< via:2 nghttpx< x-frame-options:SAMEORIGIN< x-xss-protection:1; mode=block< x-content-type-options:nosniff<
复制代码


现在的大多数网站,都是通过 302 跳转到 HTTPS 网站来协商升级的,例如我厂的 QQ 邮箱;


Connected to mail.qq.com (183.60.15.162) port 80 (#0)> GET / HTTP/1.1> Host: mail.qq.com> User-Agent: curl/7.48.0> Accept: */*> Connection: Upgrade, HTTP2-Settings> Upgrade: h2c> HTTP2-Settings: AAMAAABkAAQAAP__>< HTTP/1.1 302 Found< Server: TWS< Connection: close< Date: Sun, 10 Apr 2016 16:58:48 GMT< Content-Type: text/html; charset=GB18030< Location: https://mail.qq.com/cgi-bin/loginpage< Content-Length: 0<
复制代码

nghttp

官方文档,安装 nghttp2 后有配套的 nghttp 客户端、nghttpd 服务器、nghttpx 反向代理、h2load 负载测试等工具。


输入命令 nghttp -nv https: //nghttp2. org (n 代表不输出,v 代表详细信息):


结果列出了连接过程中的 HTTP2 各个 Stream 信息,例如 SETTINGS Frame,HEADER Frame 等,也可以带上参数:


[  0.170] ConnectedThe negotiated protocol: h2[  0.732] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>          (niv=2)          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535][  0.732] send SETTINGS frame <length=12, flags=0x00, stream_id=0>          (niv=2)          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535][  0.732] send SETTINGS frame <length=0, flags=0x01, stream_id=0>          ; ACK          (niv=0)[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=3>          (dep_stream_id=0, weight=201, exclusive=0)[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=5>          (dep_stream_id=0, weight=101, exclusive=0)[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=7>          (dep_stream_id=0, weight=1, exclusive=0)[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=9>          (dep_stream_id=7, weight=1, exclusive=0)[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=11>          (dep_stream_id=3, weight=1, exclusive=0)[  0.732] send HEADERS frame <length=36, flags=0x25, stream_id=13>          ; END_STREAM | END_HEADERS | PRIORITY          (padlen=0, dep_stream_id=11, weight=16, exclusive=0)          ; Open new stream          :method: GET          :path: /          :scheme: https          :authority: nghttp2.org          accept: */*          accept-encoding: gzip, deflate          user-agent: nghttp2/1.9.1[  0.891] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>          ; ACK          (niv=0)[  0.891] recv (stream_id=13) :method: GET[  0.891] recv (stream_id=13) :scheme: https[  0.892] recv (stream_id=13) :path: /stylesheets/screen.css[  0.892] recv (stream_id=13) :authority: nghttp2.org[  0.892] recv (stream_id=13) accept-encoding: gzip, deflate[  0.892] recv (stream_id=13) user-agent: nghttp2/1.9.1[  0.892] recv PUSH_PROMISE frame <length=47, flags=0x04, stream_id=13>          ; END_HEADERS          (padlen=0, promised_stream_id=2)[  0.892] recv (stream_id=13) :status: 200[  0.892] recv (stream_id=13) date: Sun, 10 Apr 2016 17:00:25 GMT[  0.892] recv (stream_id=13) content-type: text/html[  0.892] recv (stream_id=13) content-length: 6646[  0.892] recv (stream_id=13) last-modified: Sun, 03 Apr 2016 06:53:14 GMT[  0.892] recv (stream_id=13) etag: "5700bdda-19f6"[  0.892] recv (stream_id=13) link: </stylesheets/screen.css>; rel=preload; as=stylesheet[  0.892] recv (stream_id=13) accept-ranges: bytes[  0.892] recv (stream_id=13) x-backend-header-rtt: 0.000663[  0.892] recv (stream_id=13) strict-transport-security: max-age=31536000[  0.892] recv (stream_id=13) server: nghttpx nghttp2/1.10.0-DEV[  0.892] recv (stream_id=13) via: 2 nghttpx[  0.892] recv (stream_id=13) x-frame-options: SAMEORIGIN[  0.892] recv (stream_id=13) x-xss-protection: 1; mode=block[  0.892] recv (stream_id=13) x-content-type-options: nosniff[  0.892] recv HEADERS frame <length=266, flags=0x04, stream_id=13>          ; END_HEADERS          (padlen=0)          ; First response header[  0.893] recv DATA frame <length=6646, flags=0x01, stream_id=13>          ; END_STREAM[  0.893] recv (stream_id=2) :status: 200[  0.893] recv (stream_id=2) date: Sun, 10 Apr 2016 17:00:25 GMT[  0.893] recv (stream_id=2) content-type: text/css[  0.893] recv (stream_id=2) content-length: 39082[  0.893] recv (stream_id=2) last-modified: Sun, 03 Apr 2016 06:53:14 GMT[  0.893] recv (stream_id=2) etag: "5700bdda-98aa"[  0.893] recv (stream_id=2) accept-ranges: bytes[  0.893] recv (stream_id=2) x-backend-header-rtt: 0.000427[  0.893] recv (stream_id=2) strict-transport-security: max-age=31536000[  0.893] recv (stream_id=2) server: nghttpx nghttp2/1.10.0-DEV[  0.893] recv (stream_id=2) via: 2 nghttpx[  0.893] recv (stream_id=2) x-frame-options: SAMEORIGIN[  0.893] recv (stream_id=2) x-xss-protection: 1; mode=block[  0.893] recv (stream_id=2) x-content-type-options: nosniff[  0.893] recv (stream_id=2) x-http2-push: 1[  0.893] recv HEADERS frame <length=62, flags=0x04, stream_id=2>          ; END_HEADERS          (padlen=0)          ; First push response header[  1.407] recv DATA frame <length=16384, flags=0x00, stream_id=2>[  1.563] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>          (window_size_increment=33412)[  1.740] recv DATA frame <length=16384, flags=0x00, stream_id=2>[  1.741] recv DATA frame <length=6314, flags=0x01, stream_id=2>          ; END_STREAM[  1.741] send GOAWAY frame <length=8, flags=0x00, stream_id=0>          (last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])
复制代码


还有这些参数:


-v : 显示详细信息-n : 不输出请求返回数据内容-t : 请求超时设置-w : 设置初始窗口大小-a : 解析页面获取页面上的资源-H : 给请求增加特定头部信息,例如 -H':method:PUT'-p : 设置请求权重--no-dep : 不发送依赖信息
复制代码

nghttpd

官方文档,使用 nghttpd,可以架设一个简易的支持 HTTP2 的服务器。打开附件中的示例文件,在路径 demos/nghttp/里有一个 run.sh(需要以管理员权限执行)


$ cd demos/nghttp$ sudo ./run.sh [server-push]
复制代码


就可以执行提供的 shell 脚本,第三个参数 server-push 是可选的,如果不需要 server-push 功能,直接 sudo ./run.sh 就可以了,在本地设置好 host 127.0.0.1 http2test.com 后,就可以在本地浏览器中访问了,路径是https://http2test.com/examples/dashboard/。由于自签的证书不被信任,需要安装公钥 keys/*.crt 文件并信任(Mac 中需要打开 keychain 这个软件,然后找到刚安装的证书,改为总是信任),安装信任后,打开 Chrome 就不会提示警告了;


如果需要开启 server-push 功能,输入指令 sudo ./run.sh server-push,shell 脚本里设置了-p/examples/dashboard/=/examples/dashboard/d3.js,当请求路径/examples/dashboard/时,就推送/examples/dashboard/d3.js 文件。

三、服务器准备

nginx

nginx 的 conf 文件里的设置,设置完后需要 sudo nginx -s reload,由于 nginx 的 ngx_http_v2_module 模块是替代以前的 ngx_http_spdy_module,故开启 HTTP2 支持后,就无法同时开启 SPDY 支持:


    server {        listen       443 ssl http2;        server_name  http2test.com;        ssl_certificate      $证书地址;        ssl_certificate_key  $证书私钥地址;        ssl_session_cache    shared:SSL:1m;        ssl_session_timeout  5m;        ssl_ciphers  HIGH:!aNULL:!MD5;        ssl_prefer_server_ciphers  on;        location / {            root   $静态文件地址;            index  index.html index.htm;        }    }
复制代码

h2o

这里引入下 Server Push 的概念,在上一篇概念篇有介绍道,Server Push 就是,当请求时,服务器同时将其它文件也推送过来,HTTP2 的说明中,并没有规定 Server Push 具体的实现策略,这个可由服务器和客户端自主决定:


Jetty:jetty 通过 referrer 建立了一个依赖模型,该模型可以应用在 CDN 里,方便配置;

h2o:通过 Cookie 实现了 cache aware server push——可感知缓存的服务器推送。第一次推送时,服务器端 set-cookie,将要推送的路径+etag 存入一个集合,通过算法生产指纹编码为 base64 存入 cookie,之后通过 cookie 来判断是否需要推送该文件;


这里着重介绍 h2o,为什么 h2o 要这么做呢?因为流量就是钱啊。。。客户端接收到服务器端发送的 PUSHPROMISE Frame 后,可以通过是否发送 RST Frame 来拒绝掉服务器推送的文件,但是在这个过程中,服务器推送的文件可能已经发送一部分过来了,如果客户端决定不接收服务器推送的文件,那么之前发送的部分就是浪费掉的流量,h2o 就是为了解决这个问题;在设置好 h2o 后,我们来看看第一次访问的结果:



让我们来看看第二次访问的结果:



可以看到,第二次访问时,并没有 PUSHPROMISE Frame 了,也就是说,服务器不再推送文件了。

四、开发准备

wireshark

这里讲解基本的 wireshark 使用,由于大多数的 HTTP2 都是基于 Over TLS 版,也就是需要解密才能看到正确的 HTTP2 包内容;wireshark 提供了两个方式:


使用 SSLKEYLOGFILE,使得 wireshark 可以使用 Firefox/Chrome 的解密信息


首先在 wireshark 的 Preferences -> Protocol -> SSL 配置一个可读的文件地址,然后在环境变量,例如 Mac 是~/.bashprofile:



export SSLKEYLOGFILE=$刚配置的地址


source ~/.bashprofile


通过 Terminal 打开 Firefox 或 Chrome,这样才能使用环境变量 SSLKEYLOGFILE:


open -a Google\ Chrome


该方法的局限是,只能在电脑上抓包使用,并且只能使用 Chrome 和 Firefox;


还有一个方法是配置 RSA 私钥,不过这种办法的局限是多种加密方式不支持,并且该方法必须纪录完整的 TLS 握手过程,所以建议打开浏览器访问前就已经开始监听;


配置好解密方式后,使用浏览器打开刚跑起来的 HTTP2 Demo,https: //http2test. com/examples/dashboard/,然后再筛选出输入 http2 并回车,就可以看到筛选的 HTTP2 包。


fiddler

fiddler 解密 HTTPS 采用的是中间人攻击的方法,客户端访问到 fiddler 代理服务器,然后 fiddler 代理服务器再模拟客户端访问到网站。那么,需要安装 Fiddler 的根认证证书,同时启用 HTTPS 解密功能。



对于 Fiddler 来说,对于每个机器其实下发的其实是不同的根证书,所以,一定要通过 Fiddler 的配置网页来安装证书(配置代理后,打开网站 http://ipv4.fiddler:8888,然后点击图中的 FiddlerRoot Certificate 来下载安装)



针对 iOS 及部分高版本的 Android,证书中的部分信息是必要的,有两个办法。1) 采用如图所示的设置(iOS 9 亲测可用),2) 安装使用 Fiddler CertMaker 插件



然后需要介绍的一个点是 FiddlerScript,这是一个很强大的功能。如果需要将以前调试 HTTP 的方法在 HTTPS 同样适用,需要有这些设置。部分设置可以参考 Qzone https+SPDY 实施 扩展篇:debug with https,然后之后我也会继续更新 Fiddler 调试部分的内容,请收藏哦。在 Willow 的 rule 里设置 HTTPS -> HTTP; HTTPS -> File; 都是可以生效的。


如果需要 HTTPS -> HTTPS 或者 HTTPS -> HTTP,可以采用上面链接的方法,也可以设置 oSession[“x-replywithtunnel”] = “FakeTunnel”。


if (oSession.HostnameIs("app.yourdomain.com")){    // Handle CONNECT Tunnels    if (oSession.HTTPMethodIs("CONNECT"))    {        oSession["x-replywithtunnel"] = "FakeTunnel";        return;    }
oSession.fullUrl = "http://somedomain:someport" + oSession.PathAndQuery;}
复制代码

SSL/TLS 部分小贴士

一、活用证书,提高性能

首先来看本地搭建的 HTTPS 服务:


第一个情况是,同一个 IP,但是域名不同,同时,使用的证书也不同:第一张图显示的域名是 http2test. com,第二张图显示的域名是 http2 .icese7en. com,他们使用的证书也是不同的,可以看到 TCP Stream 这一列,具有不同的序号(相同序号表明他们使用的是同一个 TCP 连接)




第二个情况是,同一个 IP,域名不同,但是使用的证书是相同的:第一张图的域名是 cdn1. http2test. com,第二张图的域名是 cdn2. http2test. com,他们使用的证书(第三张图)是泛域名*.http2test. com,他们的 TCP Stream 序号都是 30,复用同一条 TCP 连接




那么,如果域名不同,甚至都不是子域名的方式,也可以通过这一个点去优化吗?是可以的,通过证书里的 subjectAltName,我们可以在证书里管理多个不同域名,例如 google 的证书:



不过这样证书很贵就是了 - -

二、SSL/TLS 提高安全

HSTS——HTTP 严格传输协议

HSTS 主要是为了改善以下几个问题:


没办法知道一个网站是否支持 TLS:例如第一次连接时,如果没有指定协议名,会优先采用 http 协议,有安全隐患。而开启 HSTS 后,第一次(之前访问过该域名)之后的访问浏览器会自动强制使用 HTTPS 访问;


对证书问题的宽容:未开启 HSTS 时,如果证书有问题,客户端只会提示警告,而不是禁止访问,开启 HSTS 后,会被禁止访问;


mixed-content 问题:开启 HSTS 后,一个 HTTPS 页面上的同域名下的非 HTTPS 资源会自动升级为 HTTPS 访问;


要开启 HSTS,只需要服务器端在返回头中返回(不支持 IP)


Strict-Transport-Security: max-age=31536000 [; includeSubDomains] [; preload]# includeSubDomains 可以开启子域名的HSTS功能# 不过需要评估这么做的是否会有负面影响
复制代码


在 max-age 指定的时间内,浏览器都自动以 HTTPS 访问。如果需要关闭 HSTS,返回 max-age=0 就可以了。


注意


HSTS 的第一次访问仍然具有被挟持的危险,可通过 HSTS preload 来减轻影响(需要申请加入各浏览器的 preload-list);


HSTS 时间是基于本地时间计算的,如果客户端时间被篡改,可能会造成 HSTS 策略被失效绕过。


引用自关于启用 HTTPS 的一些经验分享(一)


只要你不能确保永远提供 HTTPS 服务,就不要启用。因为一旦 HSTS 生效,你再想把网站重定向为 HTTP,之前的老用户会被无限重定向,唯一的办法是换新域名

CSP——内容安全政策

CSP 是一个声明式的安全机制,原本的目的是防止 XSS 跨站脚本攻击。例如,CSP 可以完全禁止内联的 Javascript 代码的执行,控制哪些外联的 Javascript 文件可以被执行。


Content-Security-Policy: default-src 'self'; img-src *; script-src scripts.example.com
复制代码


上面的 CSP 策略是,默认允许本源的资源的访问,允许所有 URL 的图片显示,外链脚本只允许来自于 scripts.example.com 的文件执行;


Content-Security-Policy: default-src https: 'unsafe-inline' 'unsafe-eval'; connect-src https:
复制代码


上面的 CSP 策略是,默认允许来自于任何 URL 的资源,只要它是安全的 HTTPS,同时开启了内联 JS 和 eval 的执行(默认是被 CSP 禁止的),connect-src 设定了 Ajax 请求只能请求 HTTPS;(部分开启内联 JS 的执行可参考 Content Security Policy Level 2 介绍)

CSP 上报

使用 report-uri 指令,违反 CSP 策略的行为都会被上报到该 CGI


本文转载自公众号小时光茶舍(ID:gh_7322a0f167b5)。


原文链接:


https://mp.weixin.qq.com/s/Y1x0GUkfRbWEz6YsJrMTAQ


2019-08-22 20:164190

评论

发布
暂无评论
发现更多内容

极客时间产品训练营第二周总结

云随心

产品 总结 产品训练营

第二周-作业-胡赵凯

hisun胡

产品经理 产品经理训练营

目标岗位差异化对比

Geek_6a8931

Vue.js笔试题解决业务中常见问题

我是哪吒

程序员 面试 Vue 大前端

惊呆了!某东Java大咖的MySQL笔记手册流传出来了,胜过看10本书

Java架构之路

Java 程序员 架构 面试 编程语言

常见运维监控系统的技术选型

OpsMind

运维 监控系统

用APICloud开发iOS App Clip(苹果小程序)详细教程

YonBuilder低代码开发平台

小程序云开发 大前端 移动开发 APP开发

《程序员修炼之道》- 务实的哲学(1)

石云升

程序员 28天写作

Postgreshub中文资源网介绍

PostgreSQLChina

数据库 postgresql 开源 软件 开源社区

产品经理训练营第 0 期 第二次作业

孙行者

第0期 产品经理训练营

连肝7个晚上,总结了计算机网络的知识点!(共66条)

我是哪吒

程序员 面试 浏览器 计算机网络 HTTP

懂点EXCEL就行!教你利用Python做数据筛选(上)

智分析

Python Excel 数据清洗

高承实:区块链是一个技术结构组织 而不是技术

CECBC

大数据

测试一下

TJJ

极客时间产品训练营第二周作业

云随心

产品 第二周作业 产品训练营

从根上理解高性能、高并发(六):通俗易懂,高性能服务器到底是如何实现的

JackJiang

网络编程 高并发 高性能 即时通讯

应对新冠病毒传播-粤政协委员建议构建公共卫生区块链平台

CECBC

区块链 公共卫生

深圳程序员自谋生路的2020

鸠摩智首席音效师

开源 程序员 在线教育 创业者 深圳

Flink SQL 在字节跳动的优化与实践

Apache Flink

flink

图解 | 原来这就是TCP

程序员 网络协议 架构师

【面试必备】Swift 面试题及其答案

ios swift

产品思维和产品意识

ALone

搞定万亿级MySQL海量存储的索引与分表设计实战

Java架构师迁哥

红河州加速区块链等新技术与实体经济的深度融合

CECBC

数字经济

十年磨一剑,腾讯云数据库品牌重磅升级, “企业级分布式数据库TDSQL”来了!

数据君

品牌升级后,TBase更名为TDSQL和TDSQL-A,CynosDB更名为TDSQL-C

数据君

挑战前端知识点HTTP/ECMAScript

我是哪吒

大前端 HTTP ES6

腾讯云数据库品牌升级,大咖解读数据库三大变化

数据君

阿里P8亲测能实战落地的SpringCloud开发笔记已开源

996小迁

Java 程序员 架构 面试 SpringCloud

七大步骤、备战60天,4面拿下字节跳动offer:时间规划+知识点+画脑图+做笔记+看书+看视频+刷题刷题

Java 程序员 面试

LeetCode题解:389. 找不同,ASCII码求和,JavaScript,详细注释

Lee Chen

算法 大前端 LeetCode

HTTP/2探索第二篇——工具及应用_语言 & 开发_张浩然_InfoQ精选文章