Table of Contents

记录一些解决过的坑,问题 (开始自 2017 年)

Database

PostgreSQL

  • PostgreSQL 9.3.x JSON Element Parse issue
    • 问题
      • server log 里有这样的 error log: "cannot extract element from a scalar"
      • 本地没有重现:本地 pg 已经升到了 pg 9.4+ ;另一个原因是没有正确的测试数据
      • 从实际数据库中用 "©" 把错误的库导出到 .csv 再导入到本地的 pg 9.3.x 来重现问题
    • 原因
      • 在 9.3.x 中下面这些 SQL 会引起 "cannot extract element from a scalar" 错误,但 9.4+ 中不会错误
        • "SELECT ('123'::json)->>'key' AS data;" , 9.3.x 不能从 number json 取 key
        • "SELECT (null::json)->>'key' AS data;", 9.3.x 不能从 null json 取 key
    • 解决
      • 显然不能让 server 升级 pg version, 只能修改 SQL。使用 "json_extract_path_text()" / json_extract_path()" , 9.3+ 都可以保证得到 json object 的某个 key。比如: "SELECT json_extract_path_text('123'::json, 'key') AS data;"

Node.js

  • request 发送 form data 的 post 请求时固定发生 Connection timeout error
    • 问题
      • 用 node.js request 发送文件到 server 用的是 post form data 的方式,有时会出现 connection timeout。网路没有问题,文件也不是很大。实现大概如下:

        const formData = {
          file: fs.createReadStream('the file name')
        };
        request.post({url:'https://test-site.com/upload', formData: formData }, (err) => {
          /* got the timeout error here */
        });
        
    • 原因
      • client 的代码有一些失败的 retry, 当 server 返回 500 等错误时。client 会在发一次。
      • server 检查 file format,正好第一个请求 upload 了错误的文件。
      • Client 再 retry request post 时没有重新 create stream 导致 connection timeout
    • 解决
      • 可以在 retry 时 re-create stream,不过再发一次意义不大。所以最后的修改时检查错误和请求类型放弃 retry。

Java

  • 厂内某基于 Akka 系统,运行数小时或一天规律的发生 Out of memory exception
    • 问题
      • 自己模仿调用 Akka 测试,并不发生 memory leak。所以猜测是系统中某错误调用导致。也确认了不是 Akka 版本问题。
      • 试图用增大 -Xmx 的 workaround。但是也只是延长了系统工作时间,最后仍然会出现 Out of memory。
    • 解决
      • 用 jmap 监视运行过程中哪些 class 的 instances 在过多的分配。比如: jmap -histo:live <jvm pid>
      • 发生 memory leak 后用 jmap dump 出 jvm 的 memory。比如: jmap -dump:file=<dump file> <jvm pid>
      • 用 Memory Analyzer (MAT) 或其它 tools 分析 dump file。
      • 根据分析的结果,在一些位置加 logger
      • 最后发现有个原本只该发生一次的事件,发生了无数次。改对这处就没有之前的 memory leak 了。
  • Selenium WebDriver 发生 "Unable to find a free port" 的异常
    • 问题
      • 厂里的某个系统要求在一个系统 (OS) 上用 WebDriver 运行多个测试。也就是一个操作系统商要运行多个 Chrome / Firefox 以及 chromedriver / geckodriver。
      • 以 Chrome 为例,ChromeDriver 启动时相当于启动了一个 REST API Server。所以每个 ChromeDriver 需要一个 port。
      • 默认的 Selenium 实现会自动的寻找 Free port。本地测试无论是 Windows 还是 Linux 在同时启动多个 WebDriver 时都没有遇到过问题。
      • 问题只发生在 AWS 上的部份 Linux 上。在这个 Linux 环境中,所有的 WebDriver 都在试图具体占用 1024 port。所以只有第一个能成功,后启动的都会发生 "Unable to find a free port" 的异常
    • 原因
      • 在阅读了 WebDriver find free ports 的实现后。发现 WebDriver 在 Linux Find Free ports 是不同于其它 OS 的。
      • 在 Linux 中, WebDriver 会通过 Kernel 设置 net.ipv4.ip_local_port_range 来寻找可用的 Free port 的范围。
      • 比如: "net.ipv4.ip_local_port_range = 1024 50000",表示本地 Free ports 的范围是 1024 ~ 50000。WebDriver 会避开这段,所以他会只找 50000 开外的 Port
      • 在错误发生的 Linux 环境中,正好因其它原因这个设置是 "net.ipv4.ip_local_port_range = 1024 65535" (可能是想充份利用资源)。65535 是可分配的最大 Port。所以 WebDriver 无法找到 Free port 都尝试使用 1024 port
    • 解决
      • 修改 net.ipv4.ip_local_port_range ,留出足够的空间给 WebDriver
      • 一个教训是,虽然 Java 是跨平台的。但有时也会有平台差异的实现。要有时间多测发布的平台。