在游戏项目开发中,经常会向其它的服务发送一些Http请求,获取一些数据或验证。比如充值,SDK验证等。如果每次都重新创建一个新的HttpClient对象的话,当并发上来时,容易出现异常或连接失败,超时。这里可以使用HttpClient的连接池配置,减少HttpClient创建的数量,减少资源开销。
1package com.mygame.common.utils; 2 3import java.io.IOException; 4import java.security.KeyManagementException; 5import java.security.KeyStoreException; 6import java.security.NoSuchAlgorithmException; 7import org.apache.http.Header; 8import org.apache.http.HttpStatus; 9import org.apache.http.client.config.RequestConfig; 10import org.apache.http.client.methods.CloseableHttpResponse; 11import org.apache.http.client.methods.HttpGet; 12import org.apache.http.client.methods.HttpPost; 13import org.apache.http.config.Registry; 14import org.apache.http.config.RegistryBuilder; 15import org.apache.http.conn.socket.ConnectionSocketFactory; 16import org.apache.http.conn.socket.PlainConnectionSocketFactory; 17import org.apache.http.conn.ssl.SSLConnectionSocketFactory; 18import org.apache.http.conn.ssl.TrustSelfSignedStrategy; 19import org.apache.http.entity.StringEntity; 20import org.apache.http.impl.client.CloseableHttpClient; 21import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; 22import org.apache.http.impl.client.HttpClients; 23import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; 24import org.apache.http.ssl.SSLContextBuilder; 25import org.apache.http.util.EntityUtils; 26import org.slf4j.Logger; 27import org.slf4j.LoggerFactory; 28import com.alibaba.fastjson.JSON; 29 30public class GameHttpClient { 31 private static Logger logger = LoggerFactory.getLogger(GameHttpClient.class); 32 // 池化管理 33 private static PoolingHttpClientConnectionManager poolConnManager = null; 34 35 private static CloseableHttpClient httpClient;// 它是线程安全的,所有的线程都可以使用它一起发送http请求 36 static { 37 try { 38 System.out.println("初始化HttpClientTest~~~开始"); 39 SSLContextBuilder builder = new SSLContextBuilder(); 40 builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()); 41 SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build()); 42 // 配置同时支持 HTTP 和 HTPPS 43 Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslsf).build(); 44 // 初始化连接管理器 45 poolConnManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); 46 poolConnManager.setMaxTotal(640);// 同时最多连接数 47 // 设置最大路由 48 poolConnManager.setDefaultMaxPerRoute(320); 49 // 此处解释下MaxtTotal和DefaultMaxPerRoute的区别: 50 // 1、MaxtTotal是整个池子的大小; 51 // 2、DefaultMaxPerRoute是根据连接到的主机对MaxTotal的一个细分;比如: 52 // MaxtTotal=400 DefaultMaxPerRoute=200 53 // 而我只连接到http://www.abc.com时,到这个主机的并发最多只有200;而不是400; 54 // 而我连接到http://www.bac.com 和 55 // http://www.ccd.com时,到每个主机的并发最多只有200;即加起来是400(但不能超过400);所以起作用的设置是DefaultMaxPerRoute 56 // 初始化httpClient 57 httpClient = getConnection(); 58 59 System.out.println("初始化HttpClientTest~~~结束"); 60 } catch (NoSuchAlgorithmException e) { 61 e.printStackTrace(); 62 } catch (KeyStoreException e) { 63 e.printStackTrace(); 64 } catch (KeyManagementException e) { 65 e.printStackTrace(); 66 } 67 } 68 69 public static CloseableHttpClient getConnection() { 70 RequestConfig config = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(5000).setSocketTimeout(5000).build(); 71 CloseableHttpClient httpClient = HttpClients.custom() 72 // 设置连接池管理 73 .setConnectionManager(poolConnManager) 74 .setDefaultRequestConfig(config) 75 // 设置重试次数 76 .setRetryHandler(new DefaultHttpRequestRetryHandler(2, false)).build(); 77 return httpClient; 78 } 79 80 public static String httpGet(String url) { 81 HttpGet httpGet = new HttpGet(url); 82 CloseableHttpResponse response = null; 83 84 try { 85 response = httpClient.execute(httpGet); 86 String result = EntityUtils.toString(response.getEntity()); 87 int code = response.getStatusLine().getStatusCode(); 88 if (code == HttpStatus.SC_OK) { 89 return result; 90 } else { 91 logger.error("请求{}返回错误码:{},{}", url, code,result); 92 return null; 93 } 94 } catch (IOException e) { 95 logger.error("http请求异常,{}",url,e); 96 } finally { 97 try { 98 if (response != null) 99 response.close(); 100 } catch (IOException e) { 101 e.printStackTrace(); 102 } 103 } 104 return null; 105 } 106 public static String post(String uri, Object params, Header... heads) { 107 HttpPost httpPost = new HttpPost(uri); 108 CloseableHttpResponse response = null; 109 try { 110 StringEntity paramEntity = new StringEntity(JSON.toJSONString(params)); 111 paramEntity.setContentEncoding("UTF-8"); 112 paramEntity.setContentType("application/json"); 113 httpPost.setEntity(paramEntity); 114 if (heads != null) { 115 httpPost.setHeaders(heads); 116 } 117 response = httpClient.execute(httpPost); 118 int code = response.getStatusLine().getStatusCode(); 119 String result = EntityUtils.toString(response.getEntity()); 120 if (code == HttpStatus.SC_OK) { 121 return result; 122 } else { 123 logger.error("请求{}返回错误码:{},请求参数:{},{}", uri, code, params,result); 124 return null; 125 } 126 } catch (IOException e) { 127 logger.error("收集服务配置http请求异常", e); 128 } finally { 129 try { 130 if(response != null) { 131 response.close(); 132 } 133 } catch (IOException e) { 134 e.printStackTrace(); 135 } 136 } 137 return null; 138 } 139 140}
QQ交流群:66728073,197321069
