转运网站开发,国内响应式网站欣赏,wordpress 发布文章,网络服务器异常是怎么回事目录
http1.x http2.x
关键区别
详解
总结
java代码样例
1. 添加依赖 (pom.xml)
2. 生成 SSL 证书 (测试用)
3. 配置文件 (application.yml)
4. 服务端主类
5. HTTP/2 服务配置类
6. 客户端 (Java 11 HttpClient)
7. 运行步骤
8. 关键点说明 http1.x …目录
http1.x http2.x
关键区别
详解
总结
java代码样例
1. 添加依赖 (pom.xml)
2. 生成 SSL 证书 (测试用)
3. 配置文件 (application.yml)
4. 服务端主类
5. HTTP/2 服务配置类
6. 客户端 (Java 11 HttpClient)
7. 运行步骤
8. 关键点说明 http1.x http2.x
关键区别
HTTP/1.1 和 HTTP/2 是 Web 通信协议的两个主要版本HTTP/2 旨在解决 HTTP/1.1 的许多性能限制以提供更快的网页加载体验。下面是它们的主要区别 特性 HTTP/1.1 (1997年至今) HTTP/2 (2015年至今) 对性能和效率的影响 数据传输模型 基于文本的协议可读性好。 二进制分帧层协议效率更高。 二进制协议解析更快、更紧凑、更健壮。 连接复用 需要多个TCP连接通常6-8个/域名并行请求。 - 队头阻塞同一连接上的请求必须按顺序响应。 单一持久连接 多路复用。 - 请求/响应被分解为帧交错传输。 - 单个连接处理数百个并行流。 消除队头阻塞 → 减少延迟、提升并发能力。 减少TCP连接数 → 节省资源、提高效率。 头部压缩 冗余且未压缩。 - 每个请求发送完整头部如Cookie、User-Agent等。 使用HPACK压缩算法。 - 维护头部字段表发送索引和哈夫曼编码值。 大幅减少头部开销高达90%→ 加快页面加载对移动端友好。 服务器推送 无此功能。 - 客户端必须主动请求所有资源。 服务端可主动推送资源到客户端缓存。 - 在客户端请求前预知需要推送的资源如CSS/JS。 减少额外请求往返 → 提升页面渲染速度。需谨慎配置避免浪费带宽。 优先级 无显式优先级控制。 - 浏览器通过启发式规则如将CSS/JS置于更高优先级。 流可分配优先级和权重。 - 服务端据此优化资源传输顺序。 优化关键资源加载如优先发送HTML/CSS→ 提高感知性能。 安全加密 不强制HTTPS可单独使用HTTP。 虽未强制但所有主流浏览器要求HTTPS基于TLS。 事实上的加密强制 → 提高安全性但略微增加连接建立开销。
详解
二进制分帧层 ◦ HTTP/1.1消息是纯文本格式请求行、头部、正文。人类可读但解析效率低且易出错。◦ HTTP/2在应用层HTTP和传输层TCP之间引入了一个二进制分帧层。HTTP消息请求和响应被分解为更小的、格式化的二进制帧HEADERS帧、DATA帧等然后发送。接收端再将帧重组为完整的消息。这使得解析更高效、更健壮并为多路复用等特性奠定了基础。多路复用 ◦ HTTP/1.1
▪ 队头阻塞在单个TCP连接上请求必须按发出顺序得到响应。如果一个请求处理缓慢如大文件下载后面的所有请求都会被阻塞即使它们处理的资源已经准备好了。▪ 连接数限制浏览器为了解决队头阻塞和提升并行度会为同一个域名打开多个TCP连接通常是6-8个。但这增加了服务器和网络资源消耗内存、CPU、端口、慢启动、竞争带宽并且在达到限制后仍可能排队。
◦ HTTP/2
▪ 单一连接仅需一个TCP连接。▪ 流与帧HTTP/2引入了“流”的概念。每个请求/响应对在一个独立的流中进行。流被赋予唯一的ID。消息被拆分为帧后不同流的帧可以在同一个TCP连接上交错发送和接收。▪ 消除应用层队头阻塞即使一个流的响应被延迟如等待数据库查询该阻塞只影响这一个流其他流的帧可以继续传输。因此慢响应不会阻塞整个连接。这大大提高了连接的利用率和并发效率。
头部压缩 ◦ HTTP/1.1头部包含 cookie、User-Agent、Accept-* 等字段在每个请求中重复发送且未经压缩。头部大小可能超过几百字节甚至几千字节造成显著开销尤其对大量小文件请求影响很大。◦ HTTP/2使用 HPACK 压缩算法。它利用
▪ 静态哈夫曼编码对头部字段值进行高效压缩。▪ 维护客户端和服务端共享的头部字段表常用的头部字段如:method: GET :path: /index.html可以只发送一个索引号代替完整字符串。即使是动态变化的头部如 Cookie也通过记录之前的头部来避免重复发送。▪ 这大大减少了头部开销通常压缩率在 60%-90%对降低延迟尤其是高延迟网络和提高带宽利用率非常有效。
服务器推送 ◦ HTTP/1.1服务器只能被动响应客户端的请求。客户端必须解析 HTML发现所需的资源如 CSS、JS、图像然后再发送新的请求去获取它们。这增加了额外的网络往返RTT。◦ HTTP/2服务器可以在客户端明确请求之前主动将资源“推送”给客户端。例如当服务器收到对 index.html 的请求时它可以立即把 styles.css 和 script.js 一起推送过来前提是服务器知道这些资源是后续渲染 index.html 所必需的。客户端可以将这些推送的资源存储到缓存中。当它后续需要这些资源时缓存中已经有了节省了请求时间。推送是提前获取资源的一种方法。流优先级 ◦ HTTP/1.1浏览器会尝试猜测哪些资源如 CSS JS更重要并优先请求它们但协议本身没有提供优先级机制。◦ HTTP/2允许客户端在发起请求时为流指定优先级和权重依赖关系树。服务器可以利用这些信息优先处理和传输优先级高的流的帧如关键 CSS然后再传输低优先级的流如图像。这有助于优化内容的渲染顺序提升用户体验感知性能。加密要求 ◦ HTTP/1.1可以在 HTTP明文或 HTTPSHTTP over TLS上运行。◦ HTTP/2规范本身并不强制要求使用 TLS。然而在实践当中所有主要的浏览器都只支持在 HTTPSTLS上运行 HTTP/2。这意味着部署 HTTP/2 几乎必然同时启用了 HTTPS。这既提高了安全性也简化了协议部署避免了中间代理修改流量带来的问题。 总结
• HTTP/1.1 是一个成熟的、广泛部署的基础协议但它的文本格式、队头阻塞和缺乏压缩等问题限制了其性能。
• HTTP/2 通过引入二进制分帧、强制多路复用、高效头部压缩、服务器推送和优先级控制从根本上解决了 HTTP/1.1 的性能瓶颈。它在单一连接上实现高效并行显著减少了延迟提高了网络带宽的利用率从而大大加快了现代复杂网页的加载速度。同时主流浏览器要求在 HTTPS 上使用 HTTP/2也提升了整体安全性。 迁移建议 对绝大多数现代网站使用 HTTPS 并提供 HTTP/2 支持是推荐的性能和安全最佳实践。不过需要确保你的服务器和 CDN 已正确配置支持 HTTP/2。 java代码样例
下面是一个完整的 HTTP/2 实现示例包含 Spring Boot 2.x 服务端和使用 Java HttpClient 的客户端
服务端 (Spring Boot 2.7.x)
1. 添加依赖 (pom.xml)
dependencies!-- Spring Boot Starter Web --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-web/artifactIdversion2.7.18/version/dependency!-- HTTP/2 支持 --dependencygroupIdorg.apache.tomcat.embed/groupIdartifactIdtomcat-embed-core/artifactIdversion9.0.85/version/dependencydependencygroupIdorg.apache.tomcat/groupIdartifactIdtomcat-coyote/artifactIdversion9.0.85/version/dependency
/dependencies2. 生成 SSL 证书 (测试用)
keytool -genkeypair -alias http2-demo -keyalg RSA -keysize 2048 \-storetype PKCS12 -keystore http2-demo.p12 -validity 3650
# 密码: changeit
3. 配置文件 (application.yml)
server:port: 8443ssl:key-store: classpath:http2-demo.p12key-store-password: changeitkey-store-type: PKCS12key-alias: http2-demohttp2:enabled: truetomcat:max-threads: 200
4. 服务端主类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;SpringBootApplication
public class Http2ServerApplication {public static void main(String[] args) {SpringApplication.run(Http2ServerApplication.class, args);System.out.println(HTTP/2 Server running on https://localhost:8443);}RestControllerstatic class Http2Controller {GetMapping(/)public String home() {return Welcome to HTTP/2 Server!;}GetMapping(/data)public String getData() {return HTTP/2 Response: System.currentTimeMillis();}GetMapping(/push-resource)public String getPushResource() {return Pushed Resource Content;}GetMapping(/stream)public FluxString getStream() {return Flux.interval(Duration.ofMillis(500)).map(tick - Stream data # tick Instant.now());}}
}
5. HTTP/2 服务配置类
import org.apache.coyote.http2.Http2Protocol;
import org.springframework.boot.web.embedded.tomcat.TomcatConnectorCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;Configuration
public class Http2Config {Beanpublic WebServerFactoryCustomizerTomcatServletWebServerFactory tomcatCustomizer() {return factory - factory.addConnectorCustomizers(connector - {connector.addUpgradeProtocol(new Http2Protocol());});}
}
6. 客户端 (Java 11 HttpClient)
HTTP/2 客户端代码
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import javax.net.ssl.SSLContext;public class Http2Client {private static final String SERVER_URL https://localhost:8443/data;public static void main(String[] args) throws Exception {// 1. 演示HTTP/2请求singleRequest();// 2. 演示HTTP/2并发请求concurrentRequests();// 3. 演示HTTP/2服务端推送testServerPush();// 4. 演示HTTP/2流式响应streamResponse();}private static void singleRequest() throws Exception {HttpClient client createHttpClient();HttpRequest request HttpRequest.newBuilder().uri(URI.create(SERVER_URL)).GET().timeout(Duration.ofSeconds(10)).build();HttpResponseString response client.send(request, HttpResponse.BodyHandlers.ofString());System.out.println(\n 单次请求结果 );printResponse(response);}private static void concurrentRequests() {HttpClient client createHttpClient();ListCompletableFutureVoid futures new ArrayList();System.out.println(\n 并发请求 (10次) );for (int i 0; i 10; i) {final int requestId i 1;CompletableFutureVoid future CompletableFuture.runAsync(() - {try {HttpRequest request HttpRequest.newBuilder().uri(URI.create(SERVER_URL ?req requestId)).GET().build();HttpResponseString response client.send(request, HttpResponse.BodyHandlers.ofString());System.out.printf([%s] 请求 %d 完成: %s%n, response.version(), requestId, response.body());} catch (Exception e) {e.printStackTrace();}});futures.add(future);}// 等待所有请求完成CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();System.out.println(所有并发请求完成);}private static void testServerPush() throws Exception {HttpClient client createHttpClient();HttpRequest request HttpRequest.newBuilder().uri(URI.create(https://localhost:8443)).GET().build();// 处理服务端推送CompletableFutureVoid pushFuture client.sendAsync(request, HttpResponse.BodyHandlers.ofString(),// 推送处理器(initialRequest, pushRequest) - {System.out.println(\n服务端推送资源: pushRequest.uri());return CompletableFuture.completedFuture(HttpResponse.BodyHandlers.ofString());}).thenApply(pushResponse - {System.out.println(\n 服务端推送测试 );printResponse(pushResponse);return null;});pushFuture.join();}private static void streamResponse() throws Exception {HttpClient client createHttpClient();HttpRequest request HttpRequest.newBuilder().uri(URI.create(https://localhost:8443/stream)).GET().build();System.out.println(\n 流式响应 );client.sendAsync(request, HttpResponse.BodyHandlers.ofLines()).thenAccept(response - {response.body().limit(5).forEach(line - System.out.println(收到流数据: line));}).join();}private static HttpClient createHttpClient() {return HttpClient.newBuilder().version(HttpClient.Version.HTTP_2) // 强制使用HTTP/2.sslContext(insecureContext()) // 忽略证书验证 (测试用).followRedirects(HttpClient.Redirect.NORMAL).build();}private static void printResponse(HttpResponse? response) {System.out.println(协议版本: response.version());System.out.println(状态码: response.statusCode());System.out.println(响应头: );response.headers().map().forEach((k, v) - System.out.println( k : v));System.out.println(响应体: response.body());}// 创建不安全的SSL上下文 (仅用于测试!)private static SSLContext insecureContext() {try {java.security.KeyStore ks java.security.KeyStore.getInstance(PKCS12);ks.load(null, null);javax.net.ssl.TrustManagerFactory tmf javax.net.ssl.TrustManagerFactory.getInstance(PKIX);tmf.init(ks);javax.net.ssl.TrustManager[] trustManagers tmf.getTrustManagers();SSLContext sc SSLContext.getInstance(TLS);sc.init(null, trustManagers, null);return sc;} catch (Exception e) {throw new RuntimeException(SSL上下文创建失败, e);}}
}
功能说明
服务端功能
基础端点/, /data 返回简单响应流式端点/stream 返回服务器推送事件流支持HTTP/2服务端推送使用Tomcat HTTP/2实现
客户端功能
singleRequest(): 发送单个HTTP/2请求concurrentRequests(): 发送10个并发请求展示HTTP/2多路复用testServerPush(): 接收服务端推送资源streamResponse(): 处理流式响应
7. 运行步骤
启动服务端
# 将生成的 http2-demo.p12 放入 resources 目录
mvn spring-boot:run
运行客户端
java Http2Client
预期输出 单次请求结果
协议版本: HTTP_2
状态码: 200
响应头: content-type: [text/plain;charsetUTF-8]date: [Thu, 01 Jan 2024 12:00:00 GMT]
响应体: HTTP/2 Response: 1700000000000 并发请求 (10次)
[HTTP_2] 请求 1 完成: HTTP/2 Response: 1700000000001
[HTTP_2] 请求 3 完成: HTTP/2 Response: 1700000000002
[HTTP_2] 请求 2 完成: HTTP/2 Response: 1700000000001
...
所有并发请求完成服务端推送资源: https://localhost:8443/push-resource 服务端推送测试
协议版本: HTTP_2
状态码: 200
响应头: content-type: [text/plain;charsetUTF-8]
响应体: Welcome to HTTP/2 Server! 流式响应
收到流数据: Stream data #0 2024-01-01T12:00:00.123Z
收到流数据: Stream data #1 2024-01-01T12:00:00.623Z
收到流数据: Stream data #2 2024-01-01T12:00:01.123Z
8. 关键点说明
服务端配置 • 使用 Tomcat 9 内置 HTTP/2 支持• 必须启用 SSL/TLS 加密• 添加 Http2Protocol 协议升级处理器客户端特性 • 使用 Java 11 的 HttpClient• 处理服务端推送 (pushPromiseHandler)• 接收流式响应 (BodyHandlers.ofLines())• 多路复用演示10个并发请求共享单一连接安全注意 • 生产环境应使用有效证书• insecureContext() 仅用于开发和测试• 正式环境应配置信任库和证书校验 此示例完整实现了 HTTP/2 的核心特性包括二进制分帧、多路复用、服务端推送和流式响应展示了与 HTTP/1.1 相比的性能优势。