jedis 的 Unexpected end of stream 解决方案

jedis 的 Unexpected end of stream 解决方案

  • redis 服务端版本号:2.8.X
  • Jedis 客户端版本号:2.8.1
  • 单线程、无并发操作

Jedis单链接、JedisPool、ShardedJedisPool,无论使用哪一种方式对 redis 服务进行操作,均出现了 Unexpected end of stream 的问题。

通过查看源码发现,报错具体位置是:RedisInputStream 类的 ensureFill() 方法

private void ensureFill() throws JedisConnectionException {
    if (count >= limit) {
      try {
        limit = in.read(buf);
        count = 0;
        if (limit == -1) {
          throw new JedisConnectionException("Unexpected end of stream.");
        }
      } catch (IOException e) {
        throw new JedisConnectionException(e);
      }
    }
  }

解决方案:

第一步,检查 redis config 中的 client-output-buffer-limit 配置

client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 0 0 0
client-output-buffer-limit pubsub 0 0 0

请根据实际情况合理设置Redis输出缓冲区限制,确定不是因为缓冲区太小,导致链接关闭,进而引起 Unexpected end of stream ,可以临时都设置成 “0(关闭缓冲区限制)” 来验证此种场景

第二步,检查 redis config 中的 timeout 配置

当此时间设置过短时,同一个 jedis 链接,两次访问 redis 服务的时间间隔 > ${timeout} , 服务端会单方关闭这个jedis链接,第二次使用这个jedis对象 操作 redis 时,会发生 Unexpected end of stream , 可以将其设置成“0(无过期)”来验证此种场景

第三步,优化客户端代码,增加重试机制

经过前两步的调试,根据业务实际情况,调整配置,但这样并不能完全杜绝 Unexpected end of stream 的发生,比如 “网络抖动”之类的场景下,依然会发生此问题(实际生产环境中,此种情况发生概率极低),
但是为了防止此异常引起 jvm宕机,建议在代码层面上增加加重试机制。

话外篇:

使用 redis 做存储层时,有可能出现数数据不一致的情况( redis 无事务)

参考:

https://github.com/xetorthio/jedis/issues/932

https://github.com/xetorthio/jedis/issues/1029

已标记关键词 清除标记
android下载出现有时候网速很慢的时候就会出现 java.net.ProtocolException: unexpected end of stream private void downloadApkFile() { PicoLogUtils.d("downloadApkFile: "); shallDownload = true; String urlDownload = mRemoteAddress; String dirName = Environment.getExternalStorageDirectory() + "/"; File f = new File(dirName); if (!f.exists()) { f.mkdir(); } String fileName = "picovr.apk"; File file = new File(f.getAbsoluteFile() + "/" + fileName); if (file.exists()) { file.delete(); } mFilePath = file.getAbsolutePath(); InputStream is = null; OutputStream os = null; try { URL url = new URL(urlDownload); URLConnection con = url.openConnection(); HttpURLConnection httpUrlConnection = (HttpURLConnection) con; httpUrlConnection.setRequestProperty("Accept-Encoding", "identity"); httpUrlConnection.setConnectTimeout(15000); httpUrlConnection.setReadTimeout(15000); httpUrlConnection.connect(); is = httpUrlConnection.getInputStream(); totalBytes = httpUrlConnection.getContentLength(); PicoLogUtils.d("totalBytes = " + totalBytes); byte[] bs = new byte[1024]; int len; os = new FileOutputStream(mFilePath); int count = 0; while (shallDownload && ((len = is.read(bs)) != -1)) { os.write(bs, 0, len); downloadBytes += len; PicoLogUtils.d("downloadBytes = " + downloadBytes); count++; if (count == 512) { count = 0; mHandler.sendEmptyMessage(UPDATE_PROGRESS); } } mHandler.sendEmptyMessage(INSTALL_APK); } catch (Exception e) { PicoLogUtils.e("downloadApkFile Exception =:" + e); mHandler.sendEmptyMessage(INSTALL_FAIL); } finally { if (is != null) { try { is.close(); } catch (Exception e) { e.printStackTrace(); } is = null; } if (os != null) { try { os.close(); } catch (Exception e) { e.printStackTrace(); } os = null; } } } 有没有大神遇到这样的问题???求解
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页