当前位置: 首页 > news >正文

企业做网站要注意些什么咸阳市城市建设管理局网站

企业做网站要注意些什么,咸阳市城市建设管理局网站,泰安网站建设哪家不错,松江做网站公司HttpClient优化思路 使用连接池#xff08;简单粗暴#xff09; 长连接优化#xff08;特殊业务场景#xff09; httpclient和httpget复用 合理的配置参数#xff08;最大并发请求数#xff0c;各种超时时间#xff0c;重试次数#xff09; 异步请求优化#xff0…HttpClient优化思路 使用连接池简单粗暴 长连接优化特殊业务场景 httpclient和httpget复用 合理的配置参数最大并发请求数各种超时时间重试次数 异步请求优化并发 1.背景 假设有一个http的服务日调用量在千万级别。使用了httpclient来完成业务但qps上不去性能不佳需要优化。 优化之前平均执行时间是250ms 优化之后平均执行时间是80ms降低了三分之二的消耗。 2.分析 项目的原实现比较粗略就是每次请求时初始化一个httpclient生成一个httpPost对象执行然后从返回结果取出entity保存成一个字符串最后显式关闭response和client。 我们一点点分析和优化 2.1 httpclient反复创建开销 httpclient是一个线程安全的类没有必要由每个线程在每次使用时创建全局保留一个即可。 2.2 反复创建tcp连接的开销 tcp的三次握手与四次挥手两大裹脚布过程对于高频次的请求来说消耗实在太大。试想如果每次请求我们需要花费5ms用于协商过程那么对于qps为100的单系统1秒钟我们就要花500ms用于握手和挥手。又不是高级领导我们程序员就不要搞这么大做派了改成keep alive方式以实现连接复用 2.3 重复缓存entity的开销 原本的逻辑里使用了如下代码 HttpEntity entity  httpResponse.getEntity();String response  EntityUtils.toString(entity);这里我们相当于额外复制了一份content到一个字符串里而原本的httpResponse仍然保留了一份content需要被consume掉在高并发且content非常大的情况下会消耗大量内存。并且我们需要显式的关闭连接ugly。 3.实现 按上面的分析我们主要要做三件事一是单例的client二是缓存的保活连接三是更好的处理返回结果。一就不说了来说说二。 提到连接缓存很容易联想到数据库连接池。httpclient4提供了一个PoolingHttpClientConnectionManager 作为连接池。接下来我们通过以下步骤来优化 3.1 定义一个keep alive strategy 关于keep-alive本文不展开说明只提一点是否使用keep-alive要根据业务情况来定它并不是灵丹妙药。还有一点keep-alive和time_wait/close_wait之间也有不少故事。 在本业务场景里我们相当于有少数固定客户端长时间极高频次的访问服务器启用keep-alive非常合适 再多提一嘴http的keep-alive 和tcp的KEEPALIVE不是一个东西。回到正文定义一个strategy如下 ConnectionKeepAliveStrategy myStrategy  new ConnectionKeepAliveStrategy() {Overridepublic long getKeepAliveDuration(HttpResponse response, HttpContext context) {HeaderElementIterator it  new BasicHeaderElementIterator(response.headerIterator(HTTP.CONN_KEEP_ALIVE));while (it.hasNext()) {HeaderElement he  it.nextElement();String param  he.getName();String value  he.getValue();if (value ! null  param.equalsIgnoreCase(timeout)) {return Long.parseLong(value) * 1000;}}return 60 * 1000;//如果没有约定则默认定义时长为60s} };3.2 配置一个PoolingHttpClientConnectionManager PoolingHttpClientConnectionManager connectionManager  new PoolingHttpClientConnectionManager(); connectionManager.setMaxTotal(500); connectionManager.setDefaultMaxPerRoute(50);//例如默认每路由最高50并发具体依据业务来定也可以针对每个路由设置并发数。 3.3 生成httpclient httpClient  HttpClients.custom().setConnectionManager(connectionManager).setKeepAliveStrategy(kaStrategy).setDefaultRequestConfig(RequestConfig.custom().setStaleConnectionCheckEnabled(true).build()).build();❝ 注意使用setStaleConnectionCheckEnabled方法来逐出已被关闭的链接不被推荐。更好的方式是手动启用一个线程定时运行closeExpiredConnections 和closeIdleConnections方法如下所示。 ❞ public static class IdleConnectionMonitorThread extends Thread {private final HttpClientConnectionManager connMgr;private volatile boolean shutdown;public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {super();this.connMgr  connMgr;}Overridepublic void run() {try {while (!shutdown) {synchronized (this) {wait(5000);// Close expired connectionsconnMgr.closeExpiredConnections();// Optionally, close connections// that have been idle longer than 30 secconnMgr.closeIdleConnections(30, TimeUnit.SECONDS);}}} catch (InterruptedException ex) {// terminate}}public void shutdown() {shutdown  true;synchronized (this) {notifyAll();}}}3.4 使用httpclient执行method时降低开销 ❝ 这里要注意的是不要关闭connection。 ❞ 一种可行的获取内容的方式类似于把entity里的东西复制一份 res  EntityUtils.toString(response.getEntity(),UTF-8); EntityUtils.consume(response1.getEntity());但是更推荐的方式是定义一个ResponseHandler方便你我他不再自己catch异常和关闭流。在此我们可以看一下相关的源码 public T T execute(final HttpHost target, final HttpRequest request,final ResponseHandler? extends T responseHandler, final HttpContext context)throws IOException, ClientProtocolException {Args.notNull(responseHandler, Response handler);final HttpResponse response  execute(target, request, context);final T result;try {result  responseHandler.handleResponse(response);} catch (final Exception t) {final HttpEntity entity  response.getEntity();try {EntityUtils.consume(entity);} catch (final Exception t2) {// Log this exception. The original exception is more// important and will be thrown to the caller.this.log.warn(Error consuming content after an exception., t2);}if (t instanceof RuntimeException) {throw (RuntimeException) t;}if (t instanceof IOException) {throw (IOException) t;}throw new UndeclaredThrowableException(t);}// Handling the response was successful. Ensure that the content has// been fully consumed.final HttpEntity entity  response.getEntity();EntityUtils.consume(entity);//看这里看这里return result; }可以看到如果我们使用resultHandler执行execute方法会最终自动调用consume方法而这个consume方法如下所示 public static void consume(final HttpEntity entity) throws IOException {if (entity  null) {return;}if (entity.isStreaming()) {final InputStream instream  entity.getContent();if (instream ! null) {instream.close();}} }可以看到最终它关闭了输入流。 4.其他 通过以上步骤基本就完成了一个支持高并发的httpclient的写法下面是一些额外的配置和提醒 4.1 httpclient的一些超时配置 CONNECTION_TIMEOUT是连接超时时间SO_TIMEOUT是socket超时时间这两者是不同的。连接超时时间是发起请求前的等待时间socket超时时间是等待数据的超时时间。 HttpParams params  new BasicHttpParams(); //设置连接超时时间 Integer CONNECTION_TIMEOUT  2 * 1000; //设置请求超时2秒钟 根据业务调整 Integer SO_TIMEOUT  2 * 1000; //设置等待数据超时时间2秒钟 根据业务调整//定义了当从ClientConnectionManager中检索ManagedClientConnection实例时使用的毫秒级的超时时间 //这个参数期望得到一个java.lang.Long类型的值。如果这个参数没有被设置默认等于CONNECTION_TIMEOUT因此一定要设置。 Long CONN_MANAGER_TIMEOUT  500L; //在httpclient4.2.3中我记得它被改成了一个对象导致直接用long会报错后来又改回来了params.setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, CONNECTION_TIMEOUT); params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, SO_TIMEOUT); params.setLongParameter(ClientPNames.CONN_MANAGER_TIMEOUT, CONN_MANAGER_TIMEOUT); //在提交请求之前 测试连接是否可用 params.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, true);//另外设置http client的重试次数默认是3次当前是禁用掉如果项目量不到这个默认即可 httpClient.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(0, false));4.2 如果配置了nginx的话nginx也要设置面向两端的keep-alive 现在的业务里没有nginx的情况反而比较稀少。nginx默认和client端打开长连接而和server端使用短链接。 ❝ 注意client端的keepalive_timeout和keepalive_requests参数以及upstream端的keepalive参数设置这三个参数的意义在此也不再赘述。 ❞ 以上就是我的全部设置。通过这些设置成功地将原本每次请求250ms的耗时降低到了80左右效果显著。 JAR包如下 !-- httpclient -- dependencygroupIdorg.apache.httpcomponents/groupIdartifactIdhttpclient/artifactIdversion4.5.6/version /dependency代码如下 //Basic认证 private static final CredentialsProvider credsProvider  new BasicCredentialsProvider(); //httpClient private static final CloseableHttpClient httpclient; //httpGet方法 private static final HttpGet httpget; // private static final RequestConfig reqestConfig; //响应处理器 private static final ResponseHandlerString responseHandler; //jackson解析工具 private static final ObjectMapper mapper  new ObjectMapper();static {System.setProperty(http.maxConnections,50);System.setProperty(http.keepAlive, true);//设置basic校验credsProvider.setCredentials(new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM),new UsernamePasswordCredentials(, ));//创建http客户端httpclient  HttpClients.custom().useSystemProperties().setRetryHandler(new DefaultHttpRequestRetryHandler(3,true)).setDefaultCredentialsProvider(credsProvider).build();//初始化httpGethttpget  new HttpGet();//初始化HTTP请求配置reqestConfig  RequestConfig.custom().setContentCompressionEnabled(true).setSocketTimeout(100).setAuthenticationEnabled(true).setConnectionRequestTimeout(100).setConnectTimeout(100).build();httpget.setConfig(reqestConfig);//初始化response解析器responseHandler  new BasicResponseHandler(); } /** 功能返回响应* author zhangdaquan* param [url]* return org.apache.http.client.methods.CloseableHttpResponse* exception*/ public static String getResponse(String url) throws IOException {HttpGet get  new HttpGet(url);String response  httpclient.execute(get,responseHandler);return response; }/** 功能发送http请求并用net.sf.json工具解析* author zhangdaquan* param [url]* return org.json.JSONObject* exception*/ public static JSONObject getUrl(String url) throws Exception{try {httpget.setURI(URI.create(url));String response  httpclient.execute(httpget,responseHandler);JSONObject json  JSONObject.fromObject(response);return json;} catch (IOException e) {e.printStackTrace();}return null; }/** 功能发送http请求并用jackson工具解析* author zhangdaquan* param [url]* return com.fasterxml.jackson.databind.JsonNode* exception*/ public static JsonNode getUrl2(String url){try {httpget.setURI(URI.create(url));String response  httpclient.execute(httpget,responseHandler);JsonNode node  mapper.readTree(response);return node;} catch (IOException e) {e.printStackTrace();}return null; } /** 功能发送http请求并用fastjson工具解析* author zhangdaquan* param [url]* return com.fasterxml.jackson.databind.JsonNode* exception*/ public static com.alibaba.fastjson.JSONObject getUrl3(String url){try {httpget.setURI(URI.create(url));String response  httpclient.execute(httpget,responseHandler);com.alibaba.fastjson.JSONObject jsonObject  com.alibaba.fastjson.JSONObject.parseObject(response);return jsonObject;} catch (IOException e) {e.printStackTrace();}return null; }
http://www.dnsts.com.cn/news/237302.html

相关文章:

  • 做网站建设电话销售销售管理系统
  • 网站网站建设多少钱保定网站建设推广
  • 西山网站建设上市公司排名
  • 哪家做网站最好网站建设的成功经验
  • wordpress 支持手机6网站建设与优化计入什么科莫
  • 做电影资源网站手机版广西建工集团官网
  • 怎么自己做代刷网站wordpress metro
  • 容县住房和城乡建设局网站自己做网站原始代码
  • 网站制作中文版宁波正规站内优化seo
  • 手机网站编辑wordpress搭建康乐
  • 甘肃网站建设专业定制推广网页模板
  • 教育机构网站制作模板凡科互动抽奖
  • 网站不见了张北县网站建设
  • 山东招标网官方网站电子商务网站建设作用
  • 大浪网站建设网站开发需求分析模板
  • 汕头汽配网站建设徐州seo外包
  • 中国流量最大的网站排行我要看一集片做网站
  • 网站如何做3d产品展示专业科技公司网站欣赏
  • 网站建设需求范本河海大学土木专业类建设网站
  • asp 网站图标广告策划书模板word
  • 百度云 免费 网站主机公司网站建设的要点
  • 公司网站推广方案模板南京模板建站定制网站
  • 最全网站源码分享生物类培养基网站建设 中企动力
  • 网站开发工程师项目经验怎么写网站源码交易平台代码
  • 文化建设ppt东莞网站运营知名乐云seo
  • HTML5怎么做自适应网站简单的网页制作软件
  • 汽车网站代码网站一直显示建设中
  • 网站制作百度网盘单片机培训
  • ui设计怎么收费seo外链查询工具
  • seo快速排名网站优化中国宁波网手机首页