资讯详情

资讯详情

Jina 异常处理指南:Executor 错误、网络重试策略与故障上报机制

Jina 异常处理指南Executor 错误、网络重试策略与故障上报机制【免费下载链接】jina☁️ Build multimodal AI applications with cloud-native stack项目地址: https://gitcode.com/gh_mirrors/ji/jina本篇文章以 Jinajina-serve编排层Orchestration的异常处理为主线系统梳理 Executor 错误、网络级失败重试策略、故障上报协议差异以及断点调试等实战内容。读完本文你将掌握在Flow/Deployment中配置exit_on_exceptions、timeout_send、retries的正确姿势理解本地、Kubernetes 与 service mesh 三种环境下的重试差异并能通过客户端捕获错误、定位故障 Executor。总览Jina 如何优雅地处理失败在构建复杂的多模态 AI 应用时故障是不可避免的。Jina 的设计目标不是杜绝失败而是尽力恢复、优雅降级并把有用的失败信息报告给使用者。整个异常处理链路贯穿三层Executor 层requests方法抛出的异常被捕获并写入响应返回给调用方编排/网关层Gateway、Head按重试策略对失败的 Executor 调用进行重试策略随部署环境而异客户端层收到错误后抛出 Python 异常开发者据此感知与处理。下面按照错误发生在哪里 → 编排层如何重试 → 如何上报 → 如何调试的顺序展开。Executor 错误的两类发生时机Executor 层错误主要发生在两个地方处理方式完全不同1.__init__初始化失败如果 Executor 的__init__方法抛出异常整个编排Orchestration无法启动。此时 Executor runtime 会将该异常抛出编排层随即抛出RuntimeFailToStart异常。在仓库中jina/excepts.py 定义了class RuntimeFailToStart(SystemError, BaseJinaException):可见它是SystemError与BaseJinaException的联合子类属于启动期致命错误只能通过重新部署解决。2.requests方法运行期错误如果一个requests方法在运行时抛出异常错误信息会被添加到响应中并回传给客户端而不会中断网络流——使用 gRPC 或 WebSocket 协议时连接仍然可用可以继续接收后续请求。无论是哪种情况Jina Client 都会向调用方抛出一个异常开发者必须在客户端一侧捕获处理。用 exit_on_exceptions 在特定错误下终止 Executor某些异常如网络抖动、请求超时是瞬时性的Jina 可以自动恢复但某些致命错误或用户自定义错误会让 Executor 进入不可用状态此时最好让它重启而不是继续带病运行。在本地部署时Executor 一旦退出需要手动重新运行编排才能恢复可用性在 Kubernetes 上则可以自动化终止 Executor 进程 → Pod 随之终止 → autoscaler 自动创建新 Pod 替换从而自动恢复可用性。启用方式是在将 Executor 加入编排时传入exit_on_exceptions参数dep Deployment(usesMyExecutor, exit_on_exceptions[Exception, RuntimeException])该参数接受一个由 Python 内置或用户自定义 Exception/Error 类名组成的列表注意是类名字符串。源码级佐证在 worker 的请求处理逻辑 jina/serve/runtimes/worker/request_handling.py 中当requests方法抛出异常后会先记录日志、把异常写入请求对象requests[0].add_exception(ex, self._executor)、设置 gRPC 尾随元数据is-errortrue并累加失败指标随后检查if ( self.args.exit_on_exceptions and type(ex).__name__ in self.args.exit_on_exceptions ): self.logger.info(Exiting because of --exit-on-exceptions.) raise RuntimeTerminated也就是说当捕获到的异常类型名与exit_on_exceptions列表匹配时worker 会主动抛出 RuntimeTerminated 来终止自身进程从而触发上述的 Pod 重启流程。RuntimeTerminated继承自KeyboardInterrupt确保该终止信号能被 runtime 上层捕获并干净地退出。网络错误与重试策略当编排的 Gateway 无法连接某个 Executor 或 Head 时编排层会按照重试策略尝试重新连接故障 deployment对 Executor 调用的超时同样适用该策略。策略的细节取决于部署环境。如果整个策略执行完毕仍没有任何一次对 Executor 副本的调用成功请求将被中止失败信息会按照下文故障上报一节回传给客户端。超时配置timeout_send神经网络在 CPU 上的前向传播、以及其他异常昂贵的操作经常导致默认超时设置下出现超时。如果你经常遇到 Executor 调用超时可以把编排的timeout_send调大# Python deployment Deployment(timeout_sendtime_in_ms) flow Flow(timeout_sendtime_in_ms)# Orchestration YAML with 块 with: timeout_send: time_in_ms从源码看jina/orchestrate/flow/base.py 对该参数的定义为The timeout in milliseconds used when sending data requests to Executors, -1 means no timeout, disabled by default即单位为毫秒默认不启用设为-1表示不设超时。自定义重试次数retries默认重试策略可以被覆盖改为对每个 Executor 指定重试次数# Python flow Flow(retriesn)# Orchestration YAML with 块 with: retries: n源码中 jina/orchestrate/flow/base.py 注释明确Number of retries per gRPC call. If 0 it defaults to max(3, num_replicas)——即retries 0时默认取max(3, 副本数)。这一点与下文三种环境策略中的至少三次原则相互印证。在底层网络实现 jina/serve/networking/init.py 中尝试总次数按如下公式计算if retries is None or retries 0: total_num_tries max(DEFAULT_MINIMUM_RETRIES, len(connections.get_all_connections())) 1 else: total_num_tries 1 retries # try once, then do all the retries其中DEFAULT_MINIMUM_RETRIES 3见 jina/serve/networking/utils.py。可以看到未指定retries时尝试次数 max(3, 副本数) 1即最多 4 次尝试显式指定retriesn时则共尝试1 n次。这也解释了为什么文档建议在 service mesh 自带重试时设置retries0——此时只尝试 1 次避免双重重试。策略一本地部署本地部署无论 Executor 是否容器化时每个 Executor 的失败请求策略如下如果目标 Executor 有多个副本每个副本至少尝试一次直到请求成功不论副本数量请求至少尝试三次直到成功如果副本少于三个则按**轮询round-robin**方式反复尝试。这与源码中默认尝试次数 max(3, 副本数)的计算逻辑完全一致副本多则遍历所有副本副本少则至少打满三次。策略二Kubernetes 部署无 service mesh如果编排部署在 Kubernetes 中且没有 service mesh那么重试无法分发到同一 Executor 的不同副本。为什么这是 Kubernetes 与 gRPC 组合的固有限制gRPC 基于 HTTP/2 长连接K8s 默认的 kube-proxy 无法在连接层面做负载均衡导致重试始终落在同一个副本上。解决这一限制的简便方式是引入 Linkerd 等 service mesh。具体而言此时每个 Executor 的重试策略退化为请求始终在同一个副本上尝试三次或直到成功。策略三Kubernetes 部署 service meshKubernetes service mesh 可以提供负载均衡能力从而允许在 Executor 的多个副本之间进行重试分发。HintJina 支持任意 service mesh但f.to_kubernetes_yaml()输出的 YAML 已经自带 Linkerd 所需的注解。源码佐证查看 Jina 的 K8s 模板 jina/resources/k8s/template/deployment-executor.yml 与 jina/resources/k8s/template/deployment-gateway.yml可以看到 Pod 模板中都写入了linkerd.io/inject: enabled注解这正是开箱即用支持的实现来源。启用 service mesh 后每个 Executor 的重试策略为请求至少尝试三次或直到成功请求按service mesh 的配置分发到各个副本。Caution很多 service mesh 自己也有重试能力。如果同时在 mesh 层和 Jina 层配置重试可能导致双重重试等非预期行为。此时建议关闭 Jina 层的重试flow Flow(retries0) # 或 Deployment(retries0)with: retries: 0故障上报错误如何回到客户端当某个请求的重试策略被耗尽后错误会被上报给对应的客户端。上报的错误信息中包含失败 Executor 的网络地址如果存在多个副本则报告所有地址——但 Kubernetes 部署除外因为副本由 K8s 统一管理只有一个可用地址。错误信息的具体形态取决于客户端到网关的协议和错误类型下表汇总了完整对照无法连接 ExecutorCould not connect to Executor协议状态码错误信息位置gRPC14UNAVAILABLEdetails字段HTTP503SERVICE_UNAVAILABLEresponse[header][status][description]WebSocket关闭码 1011INTERNAL_ERRORWebSocket close 消息Executor 调用超时Call to Executor timed out协议状态码错误信息位置gRPC4DEADLINE_EXCEEDEDdetails字段HTTP504GATEWAY_TIMEOUTresponse[header][status][description]WebSocket关闭码 1011INTERNAL_ERRORWebSocket close 消息对于上述任何一种场景Jina Client 都会抛出一个包含错误信息的ConnectionError。注意客户端侧的异常类型同样可在 jina/excepts.py 中找到对应实现InternalNetworkError继承自grpc.aio.AioRpcError携带request_id、目标地址dest_addr和details字段正是网关向客户端传递网络失败细节的内部载体。用 epdb 在 Executor 内打断点调试标准 Python 的breakpoint()在编排上下文管理器内调用 Executor 方法时不生效。替代方案是使用epdbenhanced Python debugger它的用法与原生断点几乎一致只需先pip install epdb。Info以下代码以 Deployment 为例可以轻松改写成 Flow。✅ 正确做法 —— 使用epdb.set_trace()from jina import Deployment, Executor, requests class CustomExecutor(Executor): requests def foo(self, **kwargs): a 25 import epdb; epdb.set_trace() print(f\n\na{a}\n\n) def main(): dep Deployment(usesCustomExecutor) with dep: dep.post(on) if __name__ __main__: main() 错误做法 —— 使用原生breakpoint()from jina import Deployment, Executor, requests class CustomExecutor(Executor): requests def foo(self, **kwargs): a 25 breakpoint() print(f\n\na{a}\n\n) def main(): dep Deployment(usesCustomExecutor) with dep: dep.post(on) if __name__ __main__: main()原因在于 Executor 运行在独立进程中标准断点所依赖的交互式解释器上下文无法在编排的 runtime 进程内正确挂起。实践要点速查场景推荐配置说明瞬时网络故障不配置使用默认默认至少尝试 3 次max(3, 副本数)频繁超时CPU 推理等昂贵操作timeout_send调大单位为毫秒-1表示不限时致命错误导致 Executor 不可用exit_on_exceptions[...]触发进程终止K8s 下由 autoscaler 自动重建K8s 无 mesh 部署接受单副本三次重试受 gRPC 长连接限制无法跨副本分发K8s service mesh如 Linkerd默认开启跨副本重试若 mesh 自带重试则设retries0避免双重重试总结Jina 的异常处理是一套分层的容错体系Executor 层区分启动失败与运行期错误前者直接抛出RuntimeFailToStart后者写入响应不中断网络流网关层根据部署环境本地 / K8s / K8smesh采用不同的重试策略底层以max(3, 副本数)为默认尝试上限失败信息则按 gRPC / HTTP / WebSocket 三种协议分别以对应的状态码与字段上报给客户端最终在客户端统一抛出ConnectionError。掌握timeout_send、retries、exit_on_exceptions三个关键参数即可针对瞬时故障、昂贵运算超时与致命错误分别制定精准的恢复策略。【免费下载链接】jina☁️ Build multimodal AI applications with cloud-native stack项目地址: https://gitcode.com/gh_mirrors/ji/jina创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →