在spark任务中循环调用调用HTTP,发生的bug

由于业务需求及历史渊源,我需要在后台使用 ssh+sparkShell提交spark任务,而在spark执行的jar包中,出现了一个神奇的bug。

我需要在jar报的主类main方法中调用http以获取大量的历史数据。代码如下:

 public static String doPost(String url, String param, DataParam paramData) {
        PrintWriter out = null;
        BufferedReader in = null;
        StringBuilder result = new StringBuilder();
        HttpURLConnection conn=null;
        String returnLine = "";
        try {
    
            URL httpUrl = new URL(url);
            // 打开和URL之间的连接
          conn= (HttpURLConnection)httpUrl.openConnection();        
            // 设置连接超时
            conn.setConnectTimeout(3000000);
            // 设置读取超时
            conn.setReadTimeout(3000000);
            // 设置请求方式
            conn.setRequestMethod("POST");
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            //conn.setRequestProperty("Connection", "keep-alive");
            conn.setRequestProperty("Connection", "close");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
            // 发送POST请求,必须设置如下两行
            conn.setDoOutput(true);
            conn.setDoInput(true);
            // 获取URLConnection对象对应的输出流
            out = new PrintWriter(conn.getOutputStream());
            // 发送请求参数
            out.print(param);
            // flush输出流的缓冲
            out.flush();
            InputStream inputStream = conn.getInputStream();
            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(inputStream));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }

        } catch (Exception e) {
            e.printStackTrace();
            //自己封装的日志,不用在意
            LogUtils.printlog("HTTP POST error : {"+e.getMessage()+"}", paramData);
        } finally {
            try {
                if (out != null) out.close();
                if (in != null) in.close();
                conn.disconnect();
            } catch (IOException ex) {
                ex.printStackTrace();
                LogUtils.printlog("HTTP POST error : {"+ex.getMessage()+"}", paramData);
            }
        }

        return returnLine;

这时候历史数据过大,导致了OOM,如下图。明显是在readLine()时溢出了。

Exception in thread "main" java.lang.OutOfMemoryError
    at java.lang.StringBuffer.append(StringBuffer.java:367)
	at java.io.BufferedReader.readLine(BufferedReader.java:370)
	at java.io.BufferedReader.readLine(BufferedReader.java:389)
	at com.cloudata.utils.DataPlatformUtil.doPost(DataPlatformUtil.java:73)

后来我也想过是数据太大,于是我根据获取历史数据的时间,按照每天或者每小时进行切割,循环调用接口。于是可怕的一幕出现了。这也是相当灵异。for循环的第一次可以正常返回数据,第二次调用时,这个地方报错了。

    报错如下:

HTTP POST error : {org.apache.hadoop.fs.FsUrlConnection cannot be cast to java.net.HttpURLConnection

我惊呆了,在我笔记本上测试时无问题的,但是上服务器就报错,我开始意识到可能是Connection连接或者流的问题。我检查了很久,没发现什么问题,我尝试将属性从 

conn.setRequestProperty("Connection", "keep-alive");

改为

conn.setRequestProperty("Connection", "close");

然而并没有用,因为我确定是这里面有问题,但找不到,问题还着急上线,我就把http换成CloseableHttpClient了。速度稍微受点影响,但问题解决了。

public static String  doPost(String url,String json,DataParam dataParam){
        LogUtils.printlog("url : {"+url+"}" +
                "param : {"+json+"}", dataParam);
        // 创建httpclient对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(300 * 1000)
                .setConnectTimeout(300 * 1000).build();
        // 创建post方式请求对象
        HttpPost post = new HttpPost(url);
        post.setConfig(requestConfig);
        // 请求的数据包为raw,设置报文头为Content-Type
        post.setHeader("Content-Type", "application/json;charset=utf-8");
        // 装载参数
        StringEntity postingString = new StringEntity(json.toString(), "utf-8");
        post.setEntity(postingString);
        // 执行请求并拿到结果
        HttpResponse response = null;
        String content = null;
        try {
            response = httpClient.execute(post);
            // 判断返回状态是否正常
            int state = response.getStatusLine().getStatusCode();
            if (state != HttpStatus.SC_OK) {
                LogUtils.printlog("HTTP POST error : {"+"connection faild 错误代码:"+state+"}", dataParam);
            }
            // 获取结果实体并返回结果
            HttpEntity entity = response.getEntity();
            content = EntityUtils.toString(entity);
            httpClient.close();
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
               LogUtils.printlog("HTTP POST error : {"+e.getMessage()+"}", dataParam);
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            LogUtils.printlog("HTTP POST error : {"+e.getMessage()+"}", dataParam);
        }
        return content;
    }

虽然问题解决了,但是以上先的两个问题并没有真真解决,特别是循环调用第二次出现连接转化异常,我非常纳闷,希望有大神可以提示一下。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值