httpclient 设置超时时间_面试官:技术选型,HttpClient还是OkHttp?
你知道的越多,不知道的就越多,业余的像一棵小草!
你来,我们一起精进!你不来,我和你的竞争对手一起精进!
编辑:业余草
来源:juejin.im/post/6844904040644476941
推荐:https://www.xttblog.com/?p=5097
写在前面
为什么会写这篇文章,起因于和朋友的聊天
这又触及到我的知识盲区了,首先来一波面向百度学习,直接根据关键字 httpclient 和 okhttp 的区别、性能比较进行搜索,没有找到想要的答案,于是就去 overstackflow 上看看是不是有人问过这个问题,果然不会让你失望的
所以从使用、性能、超时配置方面进行比较
使用
HttpClient 和 OkHttp 一般用于调用其它服务,一般服务暴露出来的接口都为 http,http 常用请求类型就为 GET、PUT、POST 和 DELETE,因此主要介绍这些请求类型的调用
HttpClient 使用介绍
使用 HttpClient 发送请求主要分为一下几步骤:
- 创建 CloseableHttpClient 对象或 CloseableHttpAsyncClient 对象,前者同步,后者为异步
- 创建 Http 请求对象
- 调用 execute 方法执行请求,如果是异步请求在执行之前需调用 start 方法
创建连接:
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
该连接为同步连接
GET 请求:
@Testpublic void testGet() throws IOException { String api = "/api/files/1"; String url = String.format("%s%s", BASE\_URL, api); HttpGet httpGet = new HttpGet(url); CloseableHttpResponse response = httpClient.execute(httpGet); System.out.println(EntityUtils.toString(response.getEntity()));}
使用 HttpGet 表示该连接为 GET 请求,HttpClient 调用 execute 方法发送 GET 请求
PUT 请求:
@Testpublic void testPut() throws IOException { String api = "/api/user"; String url = String.format("%s%s", BASE\_URL, api); HttpPut httpPut = new HttpPut(url); UserVO userVO = UserVO.builder().name("h2t").id(16L).build(); httpPut.setHeader("Content-Type", "application/json;charset=utf8"); httpPut.setEntity(new StringEntity(JSONObject.toJSONString(userVO), "UTF-8")); CloseableHttpResponse response = httpClient.execute(httpPut); System.out.println(EntityUtils.toString(response.getEntity()));}
POST 请求:
- 添加对象
@Testpublic void testPost() throws IOException { String api = "/api/user"; String url = String.format("%s%s", BASE\_URL, api); HttpPost httpPost = new HttpPost(url); UserVO userVO = UserVO.builder().name("h2t2").build(); httpPost.setHeader("Content-Type", "application/json;charset=utf8"); httpPost.setEntity(new StringEntity(JSONObject.toJSONString(userVO), "UTF-8")); CloseableHttpResponse response = httpClient.execute(httpPost); System.out.println(EntityUtils.toString(response.getEntity()));}
该请求是一个创建对象的请求,需要传入一个 json 字符串
- 上传文件
@Testpublic void testUpload1() throws IOException { String api = "/api/files/1"; String url = String.format("%s%s", BASE\_URL, api); HttpPost httpPost = new HttpPost(url); File file = new File("C:/Users/hetiantian/Desktop/学习/docker\_practice.pdf"); FileBody fileBody = new FileBody(file); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setMode(HttpMultipartMode.BROWSER\_COMPATIBLE); builder.addPart("file", fileBody); //addPart上传文件 HttpEntity entity = builder.build(); httpPost.setEntity(entity); CloseableHttpResponse response = httpClient.execute(httpPost); System.out.println(EntityUtils.toString(response.getEntity()));}
通过 addPart 上传文件
DELETE 请求:
@Testpublic void testDelete() throws IOException { String api = "/api/user/12"; String url = String.format("%s%s", BASE\_URL, api); HttpDelete httpDelete = new HttpDelete(url); CloseableHttpResponse response = httpClient.execute(httpDelete); System.out.println(EntityUtils.toString(response.getEntity()));}
请求的取消:
@Testpublic void testCancel() throws IOException { String api = "/api/files/1"; String url = String.format("%s%s", BASE\_URL, api); HttpGet httpGet = new HttpGet(url); httpGet.setConfig(requestConfig); //设置超时时间 //测试连接的取消
long begin = System.currentTimeMillis(); CloseableHttpResponse response = httpClient.execute(httpGet); while (true) { if (System.currentTimeMillis() - begin > 1000) { httpGet.abort(); System.out.println("task canceled"); break; } }
System.out.println(EntityUtils.toString(response.getEntity()));}
调用 abort 方法取消请求 执行结果:
task canceledcost 8098 mscDisconnected from the target VM, address: '127.0.0.1:60549', transport: 'socket'
java.net.SocketException: socket closed...【省略】
OkHttp 使用
使用 OkHttp 发送请求主要分为一下几步骤:
- 创建 OkHttpClient 对象
- 创建 Request 对象
- 将 Request 对象封装为 Call
- 通过 Call 来执行同步或异步请求,调用 execute 方法同步执行,调用 enqueue 方法异步执行
创建连接:
private OkHttpClient client = new OkHttpClient();
GET 请求:
@Testpublic void testGet() throws IOException { String api = "/api/files/1"; String url = String.format("%s%s", BASE\_URL, api); Request request = new Request.Builder() .url(url) .get() .build(); final Call call = client.newCall(request); Response response = call.execute(); System.out.println(response.body().string());}
PUT 请求:
@Testpublic void testPut() throws IOException { String api = "/api/user"; String url = String.format("%s%s", BASE\_URL, api); //请求参数 UserVO userVO = UserVO.builder().name("h2t").id(11L).build(); RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), JSONObject.toJSONString(userVO)); Request request = new Request.Builder() .url(url) .put(requestBody) .build(); final Call call = client.newCall(request); Response response = call.execute(); System.out.println(response.body().string());}
POST 请求:
- 添加对象
@Testpublic void testPost() throws IOException { String api = "/api/user"; String url = String.format("%s%s", BASE\_URL, api); //请求参数 JSONObject json = new JSONObject(); json.put("name", "hetiantian"); RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), String.valueOf(json)); Request request = new Request.Builder() .url(url) .post(requestBody) //post请求 .build(); final Call call = client.newCall(request); Response response = call.execute(); System.out.println(response.body().string());}
- 上传文件
@Testpublic void testUpload() throws IOException { String api = "/api/files/1"; String url = String.format("%s%s", BASE\_URL, api); RequestBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("file", "docker\_practice.pdf", RequestBody.create(MediaType.parse("multipart/form-data"), new File("C:/Users/hetiantian/Desktop/学习/docker\_practice.pdf"))) .build(); Request request = new Request.Builder() .url(url) .post(requestBody) //默认为GET请求,可以不写 .build(); final Call call = client.newCall(request); Response response = call.execute(); System.out.println(response.body().string());}
通过 addFormDataPart 方法模拟表单方式上传文件
DELETE 请求:
@Testpublic void testDelete() throws IOException { String url = String.format("%s%s", BASE\_URL, api); //请求参数 Request request = new Request.Builder() .url(url) .delete() .build(); final Call call = client.newCall(request); Response response = call.execute(); System.out.println(response.body().string());}
请求的取消:
@Testpublic void testCancelSysnc() throws IOException { String api = "/api/files/1"; String url = String.format("%s%s", BASE\_URL, api); Request request = new Request.Builder() .url(url) .get() .build(); final Call call = client.newCall(request); Response response = call.execute(); long start = System.currentTimeMillis(); //测试连接的取消 while (true) { //1分钟获取不到结果就取消请求 if (System.currentTimeMillis() - start > 1000) { call.cancel(); System.out.println("task canceled"); break; } }
System.out.println(response.body().string());}
调用 cancel 方法进行取消 测试结果:
task canceledcost 9110 msc
java.net.SocketException: socket closed...【省略】
小结
- OkHttp 使用 build 模式创建对象来的更简洁一些,并且使用. post/.delete/.put/.get 方法表示请求类型,不需要像 HttpClient 创建 HttpGet、HttpPost 等这些方法来创建请求类型
- 依赖包上,如果 HttpClient 需要发送异步请求、实现文件上传,需要额外的引入异步请求依赖
<dependency> <groupId>org.apache.httpcomponentsgroupId> <artifactId>httpmimeartifactId> <version>4.5.3version> dependency>
<dependency> <groupId>org.apache.httpcomponentsgroupId> <artifactId>httpasyncclientartifactId> <version>4.5.3version> dependency>
- 请求的取消,HttpClient 使用 abort 方法,OkHttp 使用 cancel 方法,都挺简单的,如果使用的是异步 client,则在抛出异常时调用取消请求的方法即可
超时设置
HttpClient 超时设置:在 HttpClient4.3 + 版本以上,超时设置通过 RequestConfig 进行设置
private CloseableHttpClient httpClient = HttpClientBuilder.create().build();private RequestConfig requestConfig = RequestConfig.custom() .setSocketTimeout(60 \* 1000) .setConnectTimeout(60 \* 1000).build();String api = "/api/files/1";String url = String.format("%s%s", BASE\_URL, api);HttpGet httpGet = new HttpGet(url);httpGet.setConfig(requestConfig); //设置超时时间
超时时间是设置在请求类型 HttpGet 上,而不是 HttpClient 上
OkHttp 超时设置:直接在 OkHttp 上进行设置
private OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(60, TimeUnit.SECONDS)//设置连接超时时间 .readTimeout(60, TimeUnit.SECONDS)//设置读取超时时间 .build();
小结:如果 client 是单例模式,HttpClient 在设置超时方面来的更灵活,针对不同请求类型设置不同的超时时间,OkHttp 一旦设置了超时时间,所有请求类型的超时时间也就确定
HttpClient 和 OkHttp 性能比较
测试环境:
- CPU 六核
- 内存 8G
- windows10
每种测试用例都测试五次,排除偶然性
client 连接为单例:
client 连接不为单例:
单例模式下,HttpClient 的响应速度要更快一些,单位为毫秒,性能差异相差不大 非单例模式下,OkHttp 的性能更好,HttpClient 创建连接比较耗时,因为多数情况下这些资源都会写成单例模式,因此图一的测试结果更具有参考价值
总结
OkHttp 和 HttpClient 在性能和使用上不分伯仲,根据实际业务选择即可
httpclient 设置超时时间_面试官:技术选型,HttpClient还是OkHttp?相关推荐
- redis list设置过期时间_面试官:你在Redis中设置过带过期时间的Key吗?
点击上方小伟后端笔记关注公众号 每天阅读Java干货文章 熟悉Redis的同学应该知道,Redis的每个Key都可以设置一个过期时间,当达到过期时间的时候,这个key就会被自动删除. 在为key设置过 ...
- 同时设置超时时间_刚入职的小菜鸡,设错了RPC超时,搞了个线上事故
上面这张监控图,对于服务端的研发同学来说再熟悉不过了.在日常的系统维护中,『服务超时』应该属于监控报警最多的一类问题. 尤其在微服务架构下,一次请求可能要经过一条很长的链路,跨多个服务调用后才能返回结 ...
- python给函数设置超时时间_在 Linux/Mac 下为Python函数添加超时时间的方法
我们在使用 requests 这类网络请求第三方库时,可以看到它有一个参数叫做 timeout ,就是指在网络请求发出开始计算,如果超过 timeout 还没有收到返回,就抛出超时异常.(当然存在特殊 ...
- python给函数设置超时时间_在 Linux/Mac 下为Python函数添加超时时间
我们在使用 requests 这类网络请求第三方库时,可以看到它有一个参数叫做timeout,就是指在网络请求发出开始计算,如果超过 timeout 还没有收到返回,就抛出超时异常.(当然存在特殊情况 ...
- Java中HttpClient设置超时时间
CloseableHttpClient httpclient = HttpClients.createDefault(); HttpGet httpGet = new HttpGet("ht ...
- redis查看key的过期时间_面试官:你在Redis中设置过带过期时间的Key吗?
点击上方小伟后端笔记关注公众号 每天阅读Java干货文章 熟悉Redis的同学应该知道,Redis的每个Key都可以设置一个过期时间,当达到过期时间的时候,这个key就会被自动删除. 在为key设置过 ...
- HttpClient设置超时时间无效
一开始设置了超时时间但怎么设置都没有效果 后来加上了下面一行 就可以了,因为并不是连接超时,而是因为的确连接上了,但对方一直没有给返回信息,所以要等很久,现在设置了 http.socket.timeo ...
- redis查看key的过期时间_面试官:Redis过期后key是怎么样清理的?
前言 笔者一个同事面试某大厂时问到的一个问题,这里拿来讲讲:Redis过期后key是怎么样清理的? 在Redis中,对于过期key的清理主要有惰性清除,定时清理,内存不够时清理三种方法,下面我们就来具 ...
- RestTemplate 设置超时时间
项目访问量大,频繁调取其他系统接口经常出现项目后台假死现象,发现其他系统掉线重启一段时间必现.查看调用接口,同事直接引用了RestTemplate但是没有设置超时时间->_<-. 两种方式 ...
最新文章
- 不是吧!程序员今年在相亲市场上这么受欢迎?
- python自带的解释器叫做_python学习
- SpringBoot 使用注解实现消息广播功能
- Vue Cli3 项目 vue.config.js 配置
- FZU 2108 Mod problem
- ble开发 linux_嵌入式开发的必备知识点
- qq android qav,33 BK.QQAVManager 音视频管理
- rust物资刷新机制_rust资源刷新 | 手游网游页游攻略大全
- 转置矩阵使用T,Hermite矩阵、正交矩阵、酉矩阵、奇异矩阵、正规矩阵、幂等矩阵
- codeblocks怎么编程c语言,如何能使用Codeblocks进行C语言编程操作.doc
- fast无线路由器设置服务器,迅捷(Fast)FW150R无线路由器设置
- 告诉你怎样学Java才是硬道理(转自chinaitlab)
- potainer 日志_分享10个优秀的日志分析工具
- 公历转农历C语言课程设计,(只为学习)公历转农历代码以完成,请高手在此代码基础上写出个农历转公历的代码出来...
- python find_peaks 源码理解
- 生日祝福卡片 html,暖心的卡片生日祝福语
- 上海计算机5年制大专学校,上海五年一贯制大专学校有哪些
- 如何做好一个中小型企业计算机网络管理员
- WPS文档设置空格下划线
- 在计算机储存中读写速度最快的是,储存器中存储速度最快的是哪个