排查calibre-web服务阻塞问题


问题

k8s集群中使用linuxServer的linuxserver/docker-calibre-web镜像部署了janeczku/calibre-web,在211011升级了最新的镜像后,发现网页频繁出现无响应的状况:浏览器标签页持续保持转圈的状态,直到很久以后才会报超时,且从此之后所有请求都无法正常完成。

经过多次尝试,发现在前端复现该问题的操作方法是:编辑书籍,获取元数据,点击保存。

排查

  1. 首先直接用kubectl port-forward calibre-6c5c84fd4f-z2mgb 8083:12345代理方式访问集群内calibre的pod,绕过集群中pod以外的其他网络组件,比如traefik,排除集群本身问题。发现问题依旧,初步排除集群网络问题。

  2. 此时需要看calibre-web日志:经过一番搜索研究,发现该项目的日志不会输出到stdout,而是位于项目目录里的calibre-web.log文件。相应的,在容器内的位置是/app/calibre-web/calibre-web.log

  3. 日志文件中看到很多重复的日志块如下。初步怀疑是由于编辑书的元数据时请求了google scholar,但是由于返回了status code 403,而相关代码在处理请求重试时逻辑有误导致了无限重试,进一步导致阻塞了web server主线程。

    INFO {scholarly:116} Got an access denied error (403). [2021-10-13 10:10:29,801] INFO {scholarly:118} No other connections possible. [2021-10-13 10:10:29,801] INFO {scholarly:124} Will retry after 80.11549845444705 seconds (with another session). [2021-10-13 10:11:54,220] INFO {scholarly:105} Session proxy config is {} 
  4. 此时需要查看janeczku/calibre-web的代码逻辑,相关代码如下:如果pip安装了scholarly库,则会去请求google scholor,否则会跳过。而项目把一些额外的pip依赖放到了单独的requirements文件optional-requirements.txt中。

    # Improve this to check if scholarly is available in a global way, like other pythonic libraries try: from scholarly import scholarly have_scholar = True except ImportError: have_scholar = False @editbook.route("/scholarsearch/<query>",methods=['GET']) @login_required_if_no_ano @edit_required def scholar_search(query): if have_scholar: scholar_gen = scholarly.search_pubs(' '.join(query.split('+'))) i=0 result = [] for publication in scholar_gen: del publication['source'] result.append(publication) i+=1 if(i>=10): break return Response(json.dumps(result),mimetype='application/json') else: return "[]" 
  5. 查看linuxserver/docker-calibre-web中的Dockerfile可以看到确实默认安装optional-requirements.txt

本地复现

  1. 第一次在本地启动calibre-web,仅安装requirements.txt里的依赖,此时可以正常编辑书籍的元数据。

  2. pip install optional-requirements.txt后,再编辑书籍元数据,问题被复现。

  3. 本文问题的出现,和calibre web server侧的代理情况密切相关,总结如下:

    1. 首先,显然,不安装scholarly,无论对google scholar的可达性如何都不会有问题
    2. 安装启用了scholarly后,如果访问google scholar正常,也不会有问题
    3. 安装启用了scholarly后,如果访问gogole scholar返回403,则会出现本文描述的问题。
    4. 安装启用了scholarly后,如果server在国内,且未有任何proxy的情况下,经过测试,scholarly在重试超过最大次数后会抛出MaxTriesExceededException异常,在异常抛出之前server也会被阻塞,但抛出异常后恢复正常。

溯源

安装scholarly,该库提供访问google scholar的api。pip install scholarly

❯ pip show scholarly Name: scholarly Version: 1.2.2 

截取有问题的代码片段如下,可以看到访问google 得到403 status code时会导致循环无法跳出。

# scholarly/_navigator.py if resp.status_code == 200 and not has_captcha: return resp.text elif has_captcha: self.logger.info("Got a captcha request.") self._session = self.pm._handle_captcha2(pagerequest) continue # Retry request within same session elif resp.status_code == 403: self.logger.info(f"Got an access denied error (403).") if not self.pm.has_proxy(): self.logger.info("No other connections possible.") if not self.got_403: self.logger.info("Retrying immediately with another session.") else: if not self.pm._use_luminati: w = random.uniform(60, 2*60) self.logger.info("Will retry after {} seconds (with another session).".format(w)) time.sleep(w) self._new_session() self.got_403 = True continue # Retry request within same session else: self.logger.info("We can use another connection... let's try that.") else: self.logger.info(f"""Response code {resp.status_code}. Retrying...""") 

临时解决

 

docker pull lwabish/calibre-web:china

较快速的解决方法是:fork linuxserver/docker-calibre-web,在其中的dockerfile中加入pip uninstall scholarly -y,取消google scholar支持。

新构建的镜像已上传至docker hub:lwabish/calibre-web - Docker Image | Docker Hub


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM