com.caucho.servlets.TcpPool Maven / Gradle / Ivy
/*
* Copyright (c) 1998-2018 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.servlets;
import com.caucho.util.CurrentTime;
import com.caucho.util.L10N;
import com.caucho.util.Alarm;
import com.caucho.vfs.Path;
import com.caucho.vfs.ReadStream;
import com.caucho.vfs.ReadWritePair;
import com.caucho.vfs.Vfs;
import com.caucho.vfs.WriteStream;
import com.caucho.config.types.*;
import javax.servlet.GenericServlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* TCP connection pool for the HTTP proxy
*/
public class TcpPool {
static protected final Logger log =
Logger.getLogger(TcpPool.class.getName());
static final L10N L = new L10N(TcpPool.class);
private ArrayList _hosts = new ArrayList();
private Server []_servers;
private int _roundRobin;
private long _failRecoverTime = 30 * 1000L;
/**
* Adds an address
*/
public void addAddress(String address)
{
_hosts.add(address);
}
/**
* Adds a host
*/
public void addHost(String host)
{
_hosts.add(host);
}
/**
* Sets the fail recover time.
*/
public void setFailRecoverTime(Period period)
{
_failRecoverTime = period.getPeriod();
}
public int getServerCount()
{
return _hosts.size();
}
/**
* Initialize the servlet with the server's sruns.
*/
public void init()
throws ServletException
{
if (_hosts.size() == 0)
throw new ServletException(L.l("HttpProxyServlet needs at least one host."));
_servers = new Server[_hosts.size()];
for (int i = 0; i < _hosts.size(); i++) {
String host = _hosts.get(i);
_servers[i] = new Server(host);
}
}
/**
* Handle the request.
*/
public Server nextServer()
{
synchronized (this) {
long now = CurrentTime.getCurrentTime();
int startIndex = _roundRobin;
_roundRobin = (_roundRobin + 1) % _servers.length;
int bestCost = Integer.MAX_VALUE;
Server bestServer = null;
for (int i = 0; i < _servers.length; i++) {
int index = (startIndex + i) % _servers.length;
Server server = _servers[index];
if (_failRecoverTime < now - server.getLastFailTime()
&& server.getConnectionCount() < bestCost) {
bestServer = server;
bestCost = server.getConnectionCount();
}
}
if (bestServer != null)
return bestServer;
int index = _roundRobin;
_roundRobin = (_roundRobin + 1) % _servers.length;
return _servers[index];
}
}
class Server {
private Path _path;
private long _lastFailTime;
private int _connectionCount;
Server(String host)
{
if (host.startsWith("http"))
_path = Vfs.lookup(host);
else
_path = Vfs.lookup("http://" + host);
}
String getURL()
{
return _path.getURL();
}
ReadWritePair open(String uri)
throws IOException
{
try {
Path path = _path.lookup(uri);
ReadWritePair pair = path.openReadWrite();
if (pair != null) {
synchronized (this) {
_connectionCount++;
}
}
return pair;
} catch (IOException e) {
fail();
throw e;
}
}
long getLastFailTime()
{
return _lastFailTime;
}
int getConnectionCount()
{
return _connectionCount;
}
void fail()
{
_lastFailTime = CurrentTime.getCurrentTime();
}
void close()
{
synchronized (this) {
_connectionCount--;
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy