2011-04-20 16 views
12

Jetty 7.2.2 çalıştırıyorum ve bir sınır (örneğin 5000) ulaştığında, bağlantıları reddetmeye başlayacak şekilde işlemesi gereken bağlantı sayısını sınırlamak istiyorum.İskelenin kabul edeceği bağlantı sayısını nasıl sınırlarım?

Ne yazık ki, tüm Connectors yalnızca devam edip gelen bağlantıları olabildiğince hızlı kabul eder ve yapılandırılmış iş parçacığı havuzuna gönderir.

Sorun şu ki, kısıtlı bir ortamda çalışıyorum ve yalnızca 8K dosya tanıtıcılarına erişebiliyorum. Eğer bir sürü bağlantı geliyorsa, hızlıca dosya tanıtıcıları tükenebilir ve tutarsız bir duruma geçebilirim.

Tek bir seçeneğim, bir HTTP 503 Service Unavailable döndürmektir, ancak bu hala bağlantıyı kabul etmem ve yanıtlamamı gerektirir - ve bir sunucu filtresini yazarak, belki de bir yerden gelen bağlantıların sayısını takip etmem gerekir.

Bunun için daha iyi bir çözüm var mı?

cevap

9

İstek sayısının kaydını tutan ve yük çok yüksek olduğunda 503 gönderen bir çözüm bulmaya başladım. İdeal değil, ve gördüğünüz gibi, devamlılık taleplerini her zaman bırakabilmem için bir yol eklemem gerekti. Benim ihtiyaçları için iyi çalışır:

public class MaxRequestsFilter implements Filter { 

    private static Logger cat = Logger.getLogger(MaxRequestsFilter.class.getName()); 

    private static final int DEFAULT_MAX_REQUESTS = 7000; 
    private Semaphore requestPasses; 

    @Override 
    public void destroy() { 
     cat.info("Destroying MaxRequestsFilter"); 
    } 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { 

     long start = System.currentTimeMillis(); 
     cat.debug("Filtering with MaxRequestsFilter, current passes are: " + requestPasses.availablePermits()); 
     boolean gotPass = requestPasses.tryAcquire(); 
     boolean resumed = ContinuationSupport.getContinuation(request).isResumed(); 
     try { 
      if (gotPass || resumed) { 
       chain.doFilter(request, response); 
      } else { 
       ((HttpServletResponse) response).sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); 
      } 
     } finally { 
      if (gotPass) { 
       requestPasses.release(); 
      } 
     } 
     cat.debug("Filter duration: " + (System.currentTimeMillis() - start) + " resumed is: " + resumed); 
    } 

    @Override 
    public void init(FilterConfig filterConfig) throws ServletException { 

     cat.info("Creating MaxRequestsFilter"); 

     int maxRequests = DEFAULT_MAX_REQUESTS; 
     requestPasses = new Semaphore(maxRequests, true); 
    } 

} 
5

Uygulamam için Jetty konuşlandırılmamış. Ancak, Jetty'i dağıtım için diğer bazı açık kaynak projeleriyle birlikte kullandı. Bu deneyime bağlı olarak:

alıcılar: Gelen bağlantıları kabul etmeye adanmış iş parçacığı sayısı.

acceptQueueSize: İşletim sistemi reddedilmeye başlamadan önce sıraya alınabilecek bağlantı isteklerinin sayısı. Doğru anladıysam,

http://wiki.eclipse.org/Jetty/Howto/Configure_Connectors

Buna göre, daha düşük bir seviyede TCP ayardır, yapılandırmanızda bloğun altına

<Call name="addConnector"> 
    <Arg> 
     <New class="org.mortbay.jetty.nio.SelectChannelConnector"> 
     <Set name="port"><SystemProperty name="jetty.port" default="8080"/></Set> 
     <Set name="maxIdleTime">30000</Set> 
     <Set name="Acceptors">20</Set> 
     <Set name="confidentialPort">8443</Set> 
     </New> 
    </Arg> 
</Call> 
+1

sorundur, 'Acceptors' aynı hızla ellerinden ve sonra gidip daha getir, böylece işletim sınırına ulaşıldığında asla gibi bir sıraya bağlantıları dökümü olduğunu . – BigBen

4

acceptQueueSize

bunları eklemeniz gerekir Sunucu uygulaması kabul edildiğinde() inco, hızdan daha düşük bir hızda izlenecek olan gelen bağlantıların sayısını denetler. ming bağlantıları. İkinci bağımsız değişkeni http://download.oracle.com/javase/6/docs/api/java/net/ServerSocket.html#ServerSocket(int, int) bakın.

Bu, Jetty QueuedThreadPool'da sıraya alınan isteklerin sayısından tamamen farklı bir şeydir. Kuyrukta bekletilen istekleri zaten tamamen bağlı ve havuzda kullanılabilir hale getirmek için bir iş parçacığının beklemesini ve işlemlerinin başlayabilmesini bekler.

Benzer bir sorunum var. CPU'lu bir sunucu uygulamasına sahibim (hemen hemen hiç G/Ç veya beklemiyorum, bu nedenle async yardımcı olamaz). Jetty havuzundaki maksimum diş sayısını kolayca sınırlayabiliyorum, böylece diş değiştirme ek yükü yuvada tutulacak. Ancak, sıraya alınan isteklerin uzunluğunu sınırlayamıyorum. Bu, yük büyüdükçe, tepki sürelerinin sırasıyla büyüdüğü anlamına gelir;

Tüm iş parçacıklarının meşgul olup olmadığını ve sıraya alınan isteklerin sayısı N'ye ulaşmasını istiyorum, daha sonra tüm ek istekler için 503 veya başka bir hata kodu döndürerek kuyruğu sonsuza kadar büyütmek istiyorum.

Yük dengeleyici (örn., Haproxy) kullanarak eş zamanlı sunucu isteği sayısını sınırlayabileceğimin farkındayım, ancak yalnızca Jetty ile yapılabilir mi?

P.S. Bunu yazdıktan sonra, Jetty DoS filtresini keşfettim ve önceden yapılandırılmış bir eşzamanlılık düzeyi aşıldıysa, 503 ile gelen istekleri reddetmek üzere yapılandırılmış gibi görünüyor.

12

İş parçacığı havuzu, onunla ilişkili bir sıraya sahiptir. Varsayılan olarak, sınırsızdır. Ancak, bir iş parçacığı havuzu oluştururken, onu temel almak için sınırlı bir kuyruk sağlayabilirsiniz. Örneğin: Sorun benim için giderilmiş gibi görünüyor. Aksi takdirde, sınırsız sırayla sunucu, ağır yük altında başlatıldığı için dosya tanıtıcılarının dışına çıktı.

2
<Configure id="Server" class="org.eclipse.jetty.server.Server"> 
    <Set name="ThreadPool"> 
     <New class="org.eclipse.jetty.util.thread.QueuedThreadPool"> 
     <!-- specify a bounded queue --> 
     <Arg> 
      <New class="java.util.concurrent.ArrayBlockingQueue"> 
       <Arg type="int">6000</Arg> 
      </New> 
     </Arg> 
     <Set name="minThreads">10</Set> 
     <Set name="maxThreads">200</Set> 
     <Set name="detailedDump">false</Set> 
     </New> 
    </Set> 
</Configure> 
+0

SetMaxQueued üzerinde QueuedThreadPool'u çağırabilirsiniz, bu parametre ayarlandığında kendiliğinden ArrayBlockingQueue örneğini başlatacaktır. –

İlgili konular