HTTP高并发测试
Http测试主程序
1 package http; 2 import java.util.concurrent.ExecutorService; 3 import java.util.concurrent.Executors; 4 5 public class HttpTester { 6 7 /** 8 * 各个HTTP请求的URL,参数通过StringUtils.format填充 9 */ 10 static final String BASE_URL = "http://10.10.8.35:82"; 11 static final String LOAD_URL = BASE_URL + "/user/loadInitData?userId=#"; 12 static final String PICK_SUN_URL = BASE_URL 13 + "/sun/pick?userId=#&indexNum=#"; 14 static final String DROP_SUN_URL = BASE_URL + "/sun/drop?userId=#"; 15 static final String CROP_URL = BASE_URL 16 + "/farmland/crop?userId=#&landId=#&vegetableType=#"; 17 static final String GAIN_URL = BASE_URL 18 + "/farmland/gain?userId=#&landId=#"; 19 static final String CLEAR_URL = BASE_URL 20 + "/farmland/clearRot?userId=#&landId=#"; 21 static final String RIPENING_URL = BASE_URL 22 + "/farmland/ripening?userId=#&propsId=#"; 23 24 /** 25 * 以下几个为预设的HTTP请求参数 26 */ 27 static final String[] userIdArr = { "79", "100", "101", "10011", "10012", 28 "10013", "10014", "10015", "10016", "10017", "10018", "10019", 29 "10020", "10021", "10022", "10023", "10024", "10025", "10026", 30 "10027", "10028", "10029", "10030", "10031", "10032", "10033", 31 "10034", "10035", "10036", "10038", "10039", "10040", "10041", 32 "10042", "10043", "10044", "10045", "10046", "10047", "10048", 33 "10049", "10050", "10051", "10052", "10053", "10054", "10055", 34 "10056", "10057", "10058", "10059", "10060", "10061", "10062", 35 "10063", "10064", "10065", "10066", "10067", "10068", "10069", 36 "10070", "10071", "10072", "10073", "10074", "10075", "10076", 37 "10077", "10078", "10079", "10080", "10081", "10082", "10083", 38 "10084", "10085", "10086", "10087", "10088", "10089", "10090", 39 "10091", "10092", "10093", "10094", "10095", "10096", "10097", 40 "10098", "10099", "10100", "10101", "10102", "10103", "10104", 41 "10105", "10106", "10107", "10108" }; 42 43 static final int[] farmlandArr = { 1, 2, 3, 4, 5 ,6,7,8,9,10}; 44 45 static final int[] vegetableArr = { 1, 2, 3, 4, 5, 6 }; 46 47 /** 48 * @param args 49 * @throws Exception 50 */ 51 public static void main(String[] args) throws Exception { 52 53 // 并发数量 54 final int concurrentNum = 2000; 55 ExecutorService pool = Executors.newCachedThreadPool(); 56 for (int i = 0; i < concurrentNum; i++) { 57 pool.execute(new Runnable() { 58 @Override 59 public void run() { 60 while (true) { 61 try { 62 randomRequest(); 63 } catch (Exception ex) { 64 ex.printStackTrace(); 65 } 66 } 67 68 } 69 }); 70 } 71 } 72 73 /** 74 * 随机发出HTTP请求 75 * @throws Exception 76 */ 77 public static final void randomRequest() throws Exception { 78 int x = getRandom(7); 79 switch (x) { 80 case 0: 81 loadUser(); 82 break; 83 case 1: 84 pickSun(); 85 break; 86 case 2: 87 dropSun(); 88 break; 89 case 3: 90 crop(); 91 break; 92 case 4: 93 gain(); 94 break; 95 case 5: 96 clearRot(); 97 break; 98 case 6: 99 ripending(); 100 break; 101 } 102 } 103 104 public static final void loadUser() throws Exception { 105 System.out.println(HttpUtil.get(StringUtils.format(LOAD_URL, '#', 106 userIdArr[getRandom(userIdArr.length)]))); 107 } 108 109 public static final void pickSun() throws Exception { 110 print(HttpUtil.get(StringUtils.format(PICK_SUN_URL, '#', 111 userIdArr[getRandom(userIdArr.length)], getRandom(210)))); 112 } 113 114 public static final void dropSun() throws Exception { 115 print(HttpUtil.get(StringUtils.format(DROP_SUN_URL, '#', 116 userIdArr[getRandom(userIdArr.length)]))); 117 } 118 119 public static final void crop() throws Exception { 120 print(HttpUtil.get(StringUtils.format(CROP_URL, '#', 121 userIdArr[getRandom(userIdArr.length)], 122 farmlandArr[getRandom(farmlandArr.length)], 123 vegetableArr[getRandom(vegetableArr.length)]))); 124 } 125 126 public static final void gain() throws Exception { 127 print(HttpUtil.get(StringUtils.format(GAIN_URL, '#', 128 userIdArr[getRandom(userIdArr.length)], 129 farmlandArr[getRandom(farmlandArr.length)]))); 130 } 131 132 public static final void clearRot() throws Exception { 133 print(HttpUtil.get(StringUtils.format(CLEAR_URL, '#', 134 userIdArr[getRandom(userIdArr.length)], 135 farmlandArr[getRandom(farmlandArr.length)]))); 136 } 137 138 public static final void ripending() throws Exception { 139 print(HttpUtil.get(StringUtils.format(RIPENING_URL, '#', 140 userIdArr[getRandom(userIdArr.length)], 141 1780))); 142 } 143 144 public static final int getRandom(int maxNum) { 145 return (int) Math.floor(Math.random() * maxNum); 146 } 147 148 public static final void print(String str) { 149 System.out.println(str); 150 } 151 }
Http请求使用apache的httpclient
HttpUtil.java
1 package http; 2 3 import java.util.Iterator; 4 import java.util.Map; 5 6 import org.apache.commons.httpclient.HttpClient; 7 import org.apache.commons.httpclient.HttpMethod; 8 import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; 9 import org.apache.commons.httpclient.NameValuePair; 10 import org.apache.commons.httpclient.methods.GetMethod; 11 import org.apache.commons.httpclient.methods.PostMethod; 12 13 /** 14 * HTTP工具类 15 * <pre> 16 * Class Name : HttpUtil.java 17 * Modifications: 18 * @author watchdb 19 * @since 2013-5-3上午09:24:21 20 * </pre> 21 */ 22 public class HttpUtil { 23 24 protected static HttpClient m_client = null; 25 26 static { 27 MultiThreadedHttpConnectionManager httpConnectManager = new MultiThreadedHttpConnectionManager(); 28 /** 29 * 每台主机默认的最大允许连接数 30 */ 31 httpConnectManager.getParams().setDefaultMaxConnectionsPerHost(1000); 32 /** 33 * 最大允许连接数 34 */ 35 httpConnectManager.getParams().setMaxTotalConnections(1000); 36 37 m_client = new HttpClient(httpConnectManager); 38 } 39 40 /** 41 * GET mehtod 42 * 43 * @param url 44 * URL地址 45 * @return 返回响应结果 46 */ 47 public static String get(String url) { 48 String msg = null; 49 HttpMethod method = new GetMethod(url); 50 try { 51 m_client.executeMethod(method); 52 msg = method.getResponseBodyAsString(); 53 } catch (Exception e) { 54 e.printStackTrace(); 55 } finally { 56 method.releaseConnection(); 57 } 58 return msg; 59 } 60 61 /** 62 * POST method 63 * 64 * @param url 65 * URL地址 66 * @param params 67 * 待提交的参数 68 * @return 返回响应结果 69 */ 70 public static String post(String url, Map<String, String> params) { 71 String msg = null; 72 PostMethod post = new PostMethod(url); 73 try { 74 if (params != null && params.size() > 0) { 75 int paramSize = params.size(); 76 NameValuePair[] order = new NameValuePair[paramSize]; 77 78 int n = 0; 79 for (Iterator ite = params.entrySet().iterator(); ite.hasNext();) { 80 Map.Entry<String, String> entry = (Map.Entry<String, String>) ite 81 .next(); 82 order[n++] = new NameValuePair(entry.getKey(), 83 entry.getValue()); 84 } 85 post.setRequestBody(order); 86 } 87 88 m_client.executeMethod(post); 89 msg = post.getResponseBodyAsString(); 90 } catch (Exception e) { 91 e.printStackTrace(); 92 } finally { 93 post.releaseConnection(); 94 } 95 return msg; 96 } 97 }
重写了String.format,原有的效率比较低,我们这里不需要那么多功能
StringUtils.java
1 package http; 2 3 /** 4 * 字符串工具类 5 * <pre> 6 * Class Name : StringUtils.java 7 * Modifications: 8 * @author watchdb 9 * @since 2013-5-3上午09:29:41 10 * </pre> 11 */ 12 public class StringUtils { 13 14 final static char PLACEHOLDER = '?'; 15 16 /** 17 * 字符串格式化 占位符为 ? 18 * @param fmt 待格式化字符串 19 * @param args 参数 20 * @return 21 */ 22 public final static String format(String fmt, Object... args) { 23 return format(fmt, PLACEHOLDER, args); 24 } 25 26 /** 27 * 字符串格式化 28 * @param fmt 待格式化字符串 29 * @param placeholder 占位符 30 * @param args 参数 31 * @return 32 */ 33 public final static String format(String fmt,char placeholder, Object... args) { 34 if (args == null) { 35 return fmt; 36 } 37 int l = fmt.length(); 38 int n = 0; 39 StringBuilder sb = new StringBuilder(l+10); 40 char c; 41 for (int i = 0; i < l; i++) { 42 c = fmt.charAt(i); 43 if (c == placeholder) { 44 sb.append(args[n++]); 45 } else { 46 sb.append(c); 47 } 48 } 49 return sb.toString(); 50 } 51 52 /** 53 * 判断字符串是否为空 54 * 55 * @param str 56 * @return 57 */ 58 public final static boolean isBlank(String str) { 59 if (str == null || "".equals(str)) { 60 return true; 61 } 62 return false; 63 } 64 65 /** 66 * 判断字符串是否不为空 67 * 68 * @param str 69 * @return 70 */ 71 public final static boolean isNotBlank(String str) { 72 return !isBlank(str); 73 } 74 }
参考资料:
1、Connection Close in HttpClient
2、再谈应用环境下的TIME_WAIT和CLOSE_WAIT
3、HttpClient连接池抛出大量ConnectionPoolTimeoutException: Timeout waiting for connection异常排查