如何配置ring-jetty-adapter限制嵌入式Jetty的并发工作线程数
限制Ring Jetty Adapter工作线程并发数的实现方案
方案1:集成Jetty QoSFilter(你调研的方案)
ring-jetty-adapter支持通过:configurator参数自定义Jetty服务配置,无需web.xml即可注入QoSFilter,具体实现如下:
第一步:对齐依赖
在project.clj(Leiningen项目)或deps.edn(Clojure CLI项目)中添加Jetty Servlets依赖,版本需与你当前使用的ring-jetty-adapter内置的Jetty主版本保持一致,避免类冲突:
;; Leiningen 示例 [org.eclipse.jetty/jetty-servlets "你的Jetty版本号"]
注意:Jetty 11及以上版本使用
jakarta.servlet包,Jetty 10及以下版本使用javax.servlet包,后续代码中的import语句需对应调整。
第二步:代码实现
(ns your-app.core (:require [ring.adapter.jetty :as jetty] [ring.util.servlet :as servlet]) (:import (org.eclipse.jetty.servlet ServletContextHandler ServletHolder FilterMapping) (org.eclipse.jetty.servlets QoSFilter) ;; Jetty 10及以下替换为 jakarta -> javax (jakarta.servlet DispatcherType) (java.util EnumSet))) ;; 你的业务Ring Handler (defn your-ring-handler [request] {:status 200 :body "Hello World"}) ;; Jetty自定义配置器 (defn jetty-configurator [^org.eclipse.jetty.server.Server server] (let [context (ServletContextHandler. ServletContextHandler.SESSIONS) ;; 配置QoSFilter,最大并发请求数和数据库连接池一致设为20 qos-filter (doto (QoSFilter.) (.setInitParameter "maxRequests" "20") ;; 可选:请求排队最大超时时间,单位毫秒,超时返回503 (.setInitParameter "maxWait" "30000")) filter-holder (ServletHolder. qos-filter) filter-mapping (doto (FilterMapping.) (.setFilterName "QoSFilter") ;; 可按需修改为指定接口路径,无需全局限制 (.setPathSpecs (into-array String ["/*"])) (.setDispatcherTypes (EnumSet/of DispatcherType/REQUEST)))] ;; 注入Ring业务Handler (.setServlet context (ServletHolder. (servlet/servlet your-ring-handler)) "/*") (.addFilter context filter-holder filter-mapping) (.setHandler server context))) ;; 启动Jetty服务 (jetty/run-jetty your-ring-handler {:port 8080 :configurator jetty-configurator ;; 总线程池大小可以设为比20大,预留足够线程给 acceptor、selector 等非业务线程 :max-threads 50})
方案2:Ring中间件层实现(轻量替代方案)
如果不需要复杂的QoS规则,可以直接在Ring中间件层通过信号量实现并发限制,无需依赖Jetty扩展包,实现更灵活:
(ns your-app.core (:require [ring.adapter.jetty :as jetty]) (:import (java.util.concurrent Semaphore TimeUnit))) ;; 初始化信号量,许可数和数据库连接池一致为20 (def ^Semaphore request-semaphore (Semaphore. 20)) ;; 并发限制中间件 (defn wrap-concurrency-limit [handler] (fn [request] ;; 尝试获取许可,最多等待30秒 (if (.tryAcquire request-semaphore 30 TimeUnit/SECONDS) (try (handler request) (finally ;; 请求处理完成释放许可 (.release request-semaphore))) ;; 超时返回503 {:status 503 :body "服务繁忙,请稍后重试"}))) ;; 你的业务Handler,外层包装并发限制中间件 (def your-ring-handler (wrap-concurrency-limit (fn [request] {:status 200 :body "Hello World"}))) ;; 启动Jetty (jetty/run-jetty your-ring-handler {:port 8080 :max-threads 50})
内容的提问来源于stack exchange,提问作者Viktor Holmberg
相关产品推荐
相关产品推荐

