某次运营搞活动,端口耗尽,内存溢出,查代码,原来是OkHttpClient没有单列导致。
原代码:
pom
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.2.1</version>
</dependency>
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@Slf4j
public class HttpClient {
public static final String REQUESTBODY_MEDIATYPE="application/json; charset=utf-8";
public static final String REQUESTPARAM_MEDIATYPE="application/x-www-form-urlencoded; charset=utf-8";
public static final String REQUESTBODYXML_MEDIATYPE="application/xml; charset=utf-8";
public static final Integer DEFUAL_TIME_OUT= 5;
/**
* post默认使用RequestParam
* @param url
* @param json 请求参数sign=0b7a15733db14d402329cbcefeecca45×tamp=1571275708
* @return
*/
public static Optional<String> doPost(String url, String json) {
return doPost(url, json,REQUESTPARAM_MEDIATYPE,null, DEFUAL_TIME_OUT);
}
/**
* post默认使用RequestParam
* @param url
* @param json 请求参数sign=0b7a15733db14d402329cbcefeecca45×tamp=1571275708
* @param timeout 超时时间s
* @return
*/
public static Optional<String> doPost(String url, String json, Integer timeout) {
return doPost(url, json,REQUESTPARAM_MEDIATYPE,null, timeout);
}
/**
* post默认使用RequestParam
* @param url
* @param json 请求参数sign=0b7a15733db14d402329cbcefeecca45×tamp=1571275708
* @param headersParams header参数map
* @return
*/
public static Optional<String> doPost(String url, String json,Map<String, Object> headersParams) {
return doPost(url, json,REQUESTPARAM_MEDIATYPE,headersParams, DEFUAL_TIME_OUT);
}
/**
* doPost
* @param url
* @param json requestType=REQUESTPARAM_MEDIATYPE时,传入actId=104&sign=0b7a15733db14d402329cbcefeecca45×tamp=1571275708
* requestType=REQUESTBODY_MEDIATYPE时,传入{"actCode":"JIQnAnbDrkyXzJbvUnfS","accessid":"9001","sign":"433954b00d03ef14a19455859517267c","timestamp":"1571275779"}
* @param requestType RequestBody则传入 REQUESTBODY_MEDIATYPE;RequestParam则传入REQUESTPARAM_MEDIATYPE
* @return
*/
public static Optional<String> doPost(String url, String json,String requestType){
return doPost(url, json,requestType,null, DEFUAL_TIME_OUT);
}
public static Optional<String> doPost(String url, String json,String requestType,Map<String, Object> headersParams){
return doPost(url, json,requestType,headersParams, DEFUAL_TIME_OUT);
}
/**
* doPost
* @param url
* @param json REQUESTPARAM_MEDIATYPE时,传入actId=104&sign=0b7a15733db14d402329cbcefeecca45×tamp=1571275708
* REQUESTBODY_MEDIATYPE时,传入{"actCode":"JIQnAnbDrkyXzJbvUnfS","accessid":"9001","sign":"433954b00d03ef14a19455859517267c","timestamp":"1571275779"}
* @param requestType RequestBody则传入 REQUESTBODY_MEDIATYPE;RequestParam则传入REQUESTPARAM_MEDIATYPE
* @param headersParams
* @return
*/
public static Optional<String> doPost(String url, String json,String requestType,Map<String, Object> headersParams, Integer timeout) {
MediaType mediaType=MediaType.parse(requestType);
OkHttpClient httpClient = new OkHttpClient().newBuilder().connectTimeout(timeout, TimeUnit.SECONDS).readTimeout(timeout, TimeUnit.SECONDS).build();
RequestBody body = RequestBody.create(mediaType,json);
Request request = new Request.Builder()
.url(url)
.post(body).headers(setHeaders(headersParams))
.build();
try (Response response = httpClient.newCall(request).execute()) {
return Optional.of(response.body().string());
} catch (Exception e) {
log.error("post 请求 【" + url + "] 异常, 入参 [" + json + "]", e);
}
return Optional.empty();
}
public static Optional<String> doPostXml(String url, String xmlString) {
RequestBody body=RequestBody.create(MediaType.parse(REQUESTBODYXML_MEDIATYPE), xmlString);
OkHttpClient httpClient = new OkHttpClient().newBuilder().connectTimeout(10, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).build();
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = httpClient.newCall(request).execute()) {
return Optional.of(response.body().string());
} catch (Exception e) {
log.error("post 请求 【" + url + "] 异常, 入参 [" + xmlString + "]", e);
}
return Optional.empty();
}
/**
* 设置Header头
* @param headersParams
* @return
*/
private static Headers setHeaders(Map<String,Object> headersParams){
Headers headers = null;
Headers.Builder headerBuilder = new Headers.Builder();
if(headersParams != null){
for (String key:headersParams.keySet()){
headerBuilder.add(key,headersParams.get(key).toString());
}
}
headers = headerBuilder.build();
return headers;
}
/**
* get请求
* @param url
* @return
*/
public static Optional<String> get(String url) {
OkHttpClient httpClient = new OkHttpClient().newBuilder().connectTimeout(DEFUAL_TIME_OUT, TimeUnit.SECONDS).readTimeout(DEFUAL_TIME_OUT, TimeUnit.SECONDS).build();
Request request = new Request.Builder().url(url).build();
try (Response response = httpClient.newCall(request).execute()) {
return Optional.of(response.body().string());
} catch (Exception e) {
log.error("get 请求 【" + url + "] 异常", e);
}
return Optional.empty();
}
public static String getQueryString(Map<String, String> params) {
if (params == null) {
return null;
} else {
String q = "";
int i = 0;
Iterator var3 = params.entrySet().iterator();
while(var3.hasNext()) {
Map.Entry param = (Map.Entry)var3.next();
try {
q = q + param.getKey() + "=" + URLEncoder.encode(param.getValue()==null?"":param.getValue().toString(), "utf-8");
} catch (UnsupportedEncodingException var6) {
;
}
++i;
if (i != params.size()) {
q = q + "&";
}
}
return q;
}
}
public static String getQueryObject(Map<String, Object> params) {
if (params == null) {
return null;
} else {
String q = "";
int i = 0;
Iterator var3 = params.entrySet().iterator();
while(var3.hasNext()) {
Map.Entry param = (Map.Entry)var3.next();
try {
if (param.getValue() instanceof Collection) {
for (Object s : (Collection)param.getValue()) {
q = q + param.getKey() + "=" + URLEncoder.encode(param.getValue()==null?"":s.toString(), "utf-8");
}
} else {
q = q + param.getKey() + "=" + URLEncoder.encode(param.getValue()==null?"":param.getValue().toString(), "utf-8");
}
} catch (UnsupportedEncodingException var6) {
;
}
++i;
if (i != params.size()) {
q = q + "&";
}
}
return q;
}
}
}
修改后:
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
@Slf4j
public class HttpClient {
public static final String REQUESTBODY_MEDIATYPE="application/json; charset=utf-8";
public static final String REQUESTPARAM_MEDIATYPE="application/x-www-form-urlencoded; charset=utf-8";
public static final String REQUESTBODYXML_MEDIATYPE="application/xml; charset=utf-8";
public static final Integer DEFUAL_TIME_OUT= 5;
/**
* post默认使用RequestParam
* @param url
* @param json 请求参数sign=0b7a15733db14d402329cbcefeecca45×tamp=1571275708
* @return
*/
public static Optional<String> doPost(String url, String json) {
return doPost(url, json,REQUESTPARAM_MEDIATYPE,null, DEFUAL_TIME_OUT);
}
/**
* post默认使用RequestParam
* @param url
* @param json 请求参数sign=0b7a15733db14d402329cbcefeecca45×tamp=1571275708
* @param timeout 超时时间s
* @return
*/
public static Optional<String> doPost(String url, String json, Integer timeout) {
return doPost(url, json,REQUESTPARAM_MEDIATYPE,null, timeout);
}
/**
* post默认使用RequestParam
* @param url
* @param json 请求参数sign=0b7a15733db14d402329cbcefeecca45×tamp=1571275708
* @param headersParams header参数map
* @return
*/
public static Optional<String> doPost(String url, String json,Map<String, Object> headersParams) {
return doPost(url, json,REQUESTPARAM_MEDIATYPE,headersParams, DEFUAL_TIME_OUT);
}
/**
* doPost
* @param url
* @param json requestType=REQUESTPARAM_MEDIATYPE时,传入actId=104&sign=0b7a15733db14d402329cbcefeecca45×tamp=1571275708
* requestType=REQUESTBODY_MEDIATYPE时,传入{"actCode":"JIQnAnbDrkyXzJbvUnfS","accessid":"9001","sign":"433954b00d03ef14a19455859517267c","timestamp":"1571275779"}
* @param requestType RequestBody则传入 REQUESTBODY_MEDIATYPE;RequestParam则传入REQUESTPARAM_MEDIATYPE
* @return
*/
public static Optional<String> doPost(String url, String json,String requestType){
return doPost(url, json,requestType,null, DEFUAL_TIME_OUT);
}
public static Optional<String> doPost(String url, String json,String requestType,Map<String, Object> headersParams){
return doPost(url, json,requestType,headersParams, DEFUAL_TIME_OUT);
}
/**
* doPost
* @param url
* @param json REQUESTPARAM_MEDIATYPE时,传入actId=104&sign=0b7a15733db14d402329cbcefeecca45×tamp=1571275708
* REQUESTBODY_MEDIATYPE时,传入{"actCode":"JIQnAnbDrkyXzJbvUnfS","accessid":"9001","sign":"433954b00d03ef14a19455859517267c","timestamp":"1571275779"}
* @param requestType RequestBody则传入 REQUESTBODY_MEDIATYPE;RequestParam则传入REQUESTPARAM_MEDIATYPE
* @param headersParams
* @return
*/
public static Optional<String> doPost(String url, String json,String requestType,Map<String, Object> headersParams, Integer timeout) {
MediaType mediaType=MediaType.parse(requestType);
RequestBody body = RequestBody.create(mediaType,json);
Request request = new Request.Builder()
.url(url)
.post(body).headers(setHeaders(headersParams))
.build();
try (Response response = OkHttpUtil.getInstance().newCall(request).execute()) {
return Optional.of(response.body().string());
} catch (Exception e) {
log.error("post 请求 【" + url + "] 异常, 入参 [" + json + "]", e);
}
return Optional.empty();
}
public static Optional<String> doPostXml(String url, String xmlString) {
RequestBody body=RequestBody.create(MediaType.parse(REQUESTBODYXML_MEDIATYPE), xmlString);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = OkHttpUtil.getInstance().newCall(request).execute()) {
return Optional.of(response.body().string());
} catch (Exception e) {
log.error("post 请求 【" + url + "] 异常, 入参 [" + xmlString + "]", e);
}
return Optional.empty();
}
/**
* 设置Header头
* @param headersParams
* @return
*/
private static Headers setHeaders(Map<String,Object> headersParams){
Headers headers = null;
Headers.Builder headerBuilder = new Headers.Builder();
if(headersParams != null){
for (String key:headersParams.keySet()){
headerBuilder.add(key,headersParams.get(key).toString());
}
}
headers = headerBuilder.build();
return headers;
}
/**
* get请求
* @param url
* @return
*/
public static Optional<String> get(String url) {
Request request = new Request.Builder().url(url).build();
try (Response response = OkHttpUtil.getInstance().newCall(request).execute()) {
return Optional.of(response.body().string());
} catch (Exception e) {
log.error("get 请求 【" + url + "] 异常", e);
}
return Optional.empty();
}
public static String getQueryString(Map<String, String> params) {
if (params == null) {
return null;
} else {
String q = "";
int i = 0;
Iterator var3 = params.entrySet().iterator();
while(var3.hasNext()) {
Map.Entry param = (Map.Entry)var3.next();
try {
q = q + param.getKey() + "=" + URLEncoder.encode(param.getValue()==null?"":param.getValue().toString(), "utf-8");
} catch (UnsupportedEncodingException var6) {
;
}
++i;
if (i != params.size()) {
q = q + "&";
}
}
return q;
}
}
public static String getQueryObject(Map<String, Object> params) {
if (params == null) {
return null;
} else {
String q = "";
int i = 0;
Iterator var3 = params.entrySet().iterator();
while(var3.hasNext()) {
Map.Entry param = (Map.Entry)var3.next();
try {
if (param.getValue() instanceof Collection) {
for (Object s : (Collection)param.getValue()) {
q = q + param.getKey() + "=" + URLEncoder.encode(param.getValue()==null?"":s.toString(), "utf-8");
}
} else {
q = q + param.getKey() + "=" + URLEncoder.encode(param.getValue()==null?"":param.getValue().toString(), "utf-8");
}
} catch (UnsupportedEncodingException var6) {
;
}
++i;
if (i != params.size()) {
q = q + "&";
}
}
return q;
}
}
}
单列化:
import okhttp3.OkHttpClient;
import java.util.concurrent.TimeUnit;
public class OkHttpUtil {
private static volatile OkHttpClient singleton;
public static final Integer DEFAULT_TIME_OUT= 7;
private OkHttpUtil() {
}
public static OkHttpClient getInstance() {
if (singleton == null) {
synchronized (OkHttpUtil.class) {
if (singleton == null) {
singleton = new OkHttpClient()
.newBuilder()
.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS)
.readTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS)
.writeTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS)
.build();
}
}
}
return singleton;
}
}
参考地址:OkHttp使用踩坑记录总结(一):OkHttpClient单例和长连接Connection Keep-Alive_wds的博客-CSDN博客_okhttpclient 单例
该博客介绍了由于OkHttpClient未使用单例导致的端口耗尽和内存溢出问题。通过修改代码,将OkHttpClient实例化为单例,解决了资源浪费和性能瓶颈。文中提供了解决方案的详细步骤,并展示了修改前后的代码对比。

4854

被折叠的 条评论
为什么被折叠?



