JDK httpClient 详解(源码级分析)——概览及架构篇
1. 前言
2018年9月,伴随着java 11的发布,内置的httpclient正式登上了历史的舞台。此前,JDK内置的http工具URLConnection性能羸弱,操作繁琐,饱受诟病,也因此令如Apache 的 Httpclient, Square的 OKHttp 这样的第三方客户端大放异彩。新生的JDK Httpclient,拥抱了响应式流(Reactive Stream)模型,使用了JAVA 9引入的Flow api,并运用completableFuture使调用流程异步化(在IO层面实现非阻塞化),带来了性能的提升和焕然一新的使用体验。
然而,时至如今,网络上对JDK Httpclient的分析基本是泛泛而谈,多止步于基本的使用样例,缺乏对实现的分析。或许是因为目前(2021年末)JAVA8还是主流版本,又或许是开发者已习惯了使用熟悉的Http客户端。然而,尽管我们将要看到JDK内置的httpClient并不完善,但它的实现仍有许多值得学习的地方。理解Httpclient,有助于我们更好地掌握面向对象编程和异步编程,理解NIO模型,对网络编程有更深刻的理解。
从使用到源码,让我们走进JDK HttpClient的内心,见证它从初始化、建立和维护连接、收发请求、结束回收的生命历程。
本系列文章的源码分析基于 (Zulu) Open JDK 17。截止2021年末,主要分析Http1请求的主要流程。
2. 文章链接
待更新
3. 预备知识
Reactive Streams 及 Java Flow api
响应式编程是一种面向数据流和变化传播的编程范式,可以在编程语言中很方便地表达静态或动态的数据流,相关的计算模型会自动将变化的值通过数据流进行传播。
Reactive Streams 是一项倡议,旨在为具有非阻塞背压的异步流处理提供标准。 http://www.reactive-streams.org/。某种程度上,响应式流的编程方式是观察者模式和迭代器模式的结合,但其更注重的是“非阻塞”的特性。
JDK9将Reactive Streams标准所规范的相关接口,集成到官方类库中,位于java.base模块中的java.util.concurrent包下。JDK官方实现的HttpClient完全建立在响应式流模型上,结合completableFuture,使Http请求的流程完全非阻塞化。
https://zhuanlan.zhihu.com/p/41342507
Http/Https/Http2
HTTP(1/2)是基于客户端请求——服务器响应模型的相关协议。Https是在http(1/2)协议之上多套一层SSL(TLS)协议后的协议。
IO模型(BIO/NIO)
HttpClient的实现,使用了JAVA自身的NIO类库(Selector,Channel等)来完成连接建立、数据传输等功能,其背后的底层原理是操作系统提供的(同步)I/O多路复用机制:操作系统提供系统调用,调用后内核来轮询各个文件描述符是否可读或可写;当相关系统调用返回可读或可写时,此时应用程序从便可从用户缓冲器写数据到内核缓冲区,或者从内核缓冲器读数据到用户缓冲区。
怎样理解阻塞非阻塞与同步异步的区别? - 知乎 https://www.zhihu.com/question/19732473
IO多路复用到底是不是异步的? - 闪客sun的回答 - 知乎 https://www.zhihu.com/question/59975081/answer/1932776593
4. 架构图及功能简述
下面是本人阅读HttpClient源码后,总结出的架构图

简要介绍下各层的作用:
客户端层:分为外观层和实现层,主要作用是的提供调用的api,发起同步或异步的Http请求
交换层:分为多重交换层MultiExchange和单次交换层Exchange,单次交换层又委托给下面具体实现的Http1.1/Http2交换层
- MultiExchange:处理一个用户请求可能衍生出的多个请求——响应交换
- Exchange:处理单次请求——响应交换
连接层:管理Http连接,负责建立和复用Http连接的过程
管道层:负责建立、维护Socket连接及收发数据。分为Socket管道和可能存在的建立于其上的SSL管道
- Socket管道:负责向Socket通道发送或从其接收数据
- SSL管道:负责https请求的SSL认证及数据的加密、解密
见识了HttpClient的分层架构,那么它如何使用,性能如何呢?我们下回分解。
JDK httpClient 详解(源码级分析)——概览及架构篇的更多相关文章
- ArrayList详解-源码分析
ArrayList详解-源码分析 1. 概述 在平时的开发中,用到最多的集合应该就是ArrayList了,本篇文章将结合源代码来学习ArrayList. ArrayList是基于数组实现的集合列表 支 ...
- LinkedList详解-源码分析
LinkedList详解-源码分析 LinkedList是List接口的第二个具体的实现类,第一个是ArrayList,前面一篇文章已经总结过了,下面我们来结合源码,学习LinkedList. 基于双 ...
- MapReduce的ReduceTask任务的运行源码级分析
MapReduce的MapTask任务的运行源码级分析 这篇文章好不容易恢复了...谢天谢地...这篇文章讲了MapTask的执行流程.咱们这一节讲解ReduceTask的执行流程.ReduceTas ...
- MapReduce的MapTask任务的运行源码级分析
TaskTracker任务初始化及启动task源码级分析 这篇文章中分析了任务的启动,每个task都会使用一个进程占用一个JVM来执行,org.apache.hadoop.mapred.Child方法 ...
- TaskTracker任务初始化及启动task源码级分析
在监听器初始化Job.JobTracker相应TaskTracker心跳.调度器分配task源码级分析中我们分析的Tasktracker发送心跳的机制,这一节我们分析TaskTracker接受JobT ...
- Java开源生鲜电商平台-盈利模式详解(源码可下载)
Java开源生鲜电商平台-盈利模式详解(源码可下载) 该平台提供一个联合买家与卖家的一个平台.(类似淘宝购物,这里指的是食材的购买.) 平台有以下的盈利模式:(类似的平台有美菜网,食材网等) 1. 订 ...
- 监听器初始化Job、JobTracker相应TaskTracker心跳、调度器分配task源码级分析
JobTracker和TaskTracker分别启动之后(JobTracker启动流程源码级分析,TaskTracker启动过程源码级分析),taskTracker会通过心跳与JobTracker通信 ...
- TableInputFormat分片及分片数据读取源码级分析
我们在MapReduce中TextInputFormat分片和读取分片数据源码级分析 这篇中以TextInputFormat为例讲解了InputFormat的分片过程以及RecordReader读取分 ...
- MapReduce job在JobTracker初始化源码级分析
mapreduce job提交流程源码级分析(三)中已经说明用户最终调用JobTracker.submitJob方法来向JobTracker提交作业.而这个方法的核心提交方法是JobTracker.a ...
随机推荐
- Hadoop【Hadoop-HA搭建(HDFS、YARN)】
目录 0.HDFS-HA的工作机制 1. HDFS-HA集群配置 1.1 环境准备 1.2 规划集群 1.3 配置Zookeeper集群 2. 配置HDFS-HA集群 3. 启动HDFS-HA集群 4 ...
- Kafka 架构深入
Kafka 工作流程及文件存储机制
- 【leetcode】15. 3 Sum 双指针 压缩搜索空间
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i ...
- Linux基础命令---enable开启shell命令
enable enable指令用来关闭或者激活shell内部命令.此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.Fedora. 1.语法 enable [-a] ...
- SpringBoot+MybatisPlus实现批量添加的两种方式
第一种: 因为Mysql数据每次发送sql语句的长度不能超过1M,所以,每次发送insert语句以固定长度发送: 将sql语句在provider中,以固定长度装入List集合中,然后返回service ...
- 拷贝txt文本中的某行的数据到excel中
package com.hope.day01;import java.io.*;import java.util.ArrayList;public class HelloWorld { publ ...
- 【C/C++】编码(腾讯)
假定一种编码的编码范围是a ~ y的25个字母,从1位到4位的编码,如果我们把该编码按字典序排序,形成一个数组如下: a, aa, aaa, aaaa, aaab, aaac, - -, b, ba, ...
- 十二. Go并发编程--sync/errGroup
一.序 这一篇算是并发编程的一个补充,起因是当前有个项目,大概の 需求是,根据kafka的分区(partition)数,创建同等数量的 消费者( goroutine)从不同的分区中消费者消费数据,但是 ...
- Python绘制柱状图
1.1Python绘制柱状图对应代码如下所示 import matplotlib.pyplot as plt import numpy as np from pylab import mpl mpl. ...
- Linux网络编程入门
(一)Linux网络编程--网络知识介绍 Linux网络编程--网络知识介绍客户端和服务端 网络程序和普通的程序有一个最大的区别是网络程序是由两个部分组成的--客户端和服务器端. 客户 ...