写点什么

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:165022

评论

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

以智能运维一体化平台破局数字化转型深层挑战,湖北数产集团X嘉为蓝鲸

嘉为蓝鲸

数字化转型 AIOPS 一体化运维

可观测性+AI双轮驱动!嘉为蓝鲸应用发布中心V6.0打造下一代智能发布操作系统

嘉为蓝鲸

AIOPS 智能运维 应用发布中心

双引擎驱动!WeOps存储监控的全插件支持与自定义开发指南

嘉为蓝鲸

智能运维 #WeOps 监控管理

4月用友BIP行动地图发布!

用友智能财务

AI 财务 会计

AI背单词APP的线上运营

北京木奇移动技术有限公司

软件外包公司 AI英语学习 AI背单词

WebGL软件系统的性能优化方法

北京木奇移动技术有限公司

软件外包公司 webgl开发 three.js开发

DataWorks数据集成同步至Hologres能力介绍

阿里云大数据AI技术

大数据 Serverless 数据集成 hologres Dataworks

故障定位系列-2-共享连接池故障

乒乓狂魔

故障定位 AIOPS 可观测

「通义灵码+X」公开课开讲啦!和赛博同桌一起完成开发任务 有奖励

阿里云云效

阿里云 通义灵码

钉钉 + AI 网关给 DeepSeek 办入职

阿里巴巴云原生

阿里云 AI 网关

去中心化云算力的3个发展阶段,走向自治和高效

PowerVerse

发展 去中心化 算力 web3

不愧是高级Java开发岗,确实有点难~

王中阳Go

Java 面试 Java高级开发工程师

京东API接口最新指南:店铺所有商品接口的接入与使用

tbapi

京东API 京东店铺所有商品接口 京东店铺所有商品采集

嘉为蓝鲸IT服务管理中心V4.0:灵活扩展+敏捷交付,IT服务管理全链路高效协同

嘉为蓝鲸

AIOPS ITSM 智能运维 IT服务管理中心

运维人员如何抓住 AI 机遇?DeepSeek 给出的转型路线图

嘉为蓝鲸

AIOPS 智能运维 DeepSeek

实验室管理系统(源码+文档+讲解+演示)

深圳亥时科技

MobTech秒验支持H5场景,本机一键登录验证更便捷

MobTech袤博科技

秒验

怎么用最小的投入通过等保测评?一站式服务

黑龙江陆陆信息测评部

智能运维新标杆:OpsPilot V3.3通过MCP实现多源运维知识融合

嘉为蓝鲸

智能运维 #WeOps MCP协议

ArkTS编程语法基础,让你成为HarmonyOS开发高手

肥晨

「通义灵码+X」公开课开讲啦!和赛博同桌一起完成开发任务 有奖励

阿里巴巴云原生

内核探究|Apache Cloudberry 并行查询技术解析

酷克数据HashData

室内LED显示屏:如何避免伤害眼睛的眩光问题

Dylan

数字 LED显示屏 全彩LED显示屏 led显示屏厂家 户内led显示屏

云原生 Kafka 问卷调研启动,你的声音很重要!参与赢精美礼品!

阿里巴巴云原生

kafka 阿里云 云原生

智慧园区管理系统(源码+文档+讲解+演示)

深圳亥时科技

分布式数据一致性场景与方案处理分析|得物技术

得物技术

分布式 事务消息 分布式一致性 业务场景分析

秒哒首发即爆发!上线首日吸引2万用户,打造3万应用!

百度Geek说

百度

Web3项目的上线流程

北京木奇移动技术有限公司

区块链开发 软件外包公司 web3开发

AI加剧GPU短缺,解决之道在哪里?

PowerVerse

趋势 AI‘’ gpu 算力

【FAQ】HarmonyOS SDK 闭源开放能力 —Push Kit(12)

HarmonyOS SDK

harmoyos

千万级数据秒级响应!碧桂园服务技术引擎重构智慧社区新标杆

智在碧得

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