I have multiple web applications running under a single Tomcat container. Since they all run under a single Tomcat connector (as defined in the server.xml file), attributes such as maxConnections and maxThreads govern the container as a whole. As a result it is possible for a single application to consume all available Tomcat threads, starving the other applications of threads and making them unresponsive. I would like to be able to define the maximum http threads on a per context basis so that this is no longer possible.
Here's what I've tried so far:
Create a custom filter in the application that keeps track of the current thread count and limits additional connections. (Got the filter here: How to set limit to the number of concurrent request in servlet?). I'm not sure I like this solution, as it isn't as full-featured (support for attributes such as acceptCount, maxConnections, maxThreads, and minSpareThreads) as Tomcat provides by default to the container; and adding in the features feels like I am attempting to build what already exists in Tomcat.
Create a separate Tomcat connector in the server.xml file for each context. This has a few issues. For one, each connector requires a separate port; this means I'll have to account for this in my apache config. Secondly, I plan to add more webapps regularly; this means a config change followed by a tomcat restart, which is disruptive to clients.
Has anyone else encountered something like this? I feel like there should be a "Tomcat supported" workflow to accomplish what I'm after.
I'm going to post an answer that was provided to me from the Tomcat user group: http://tomcat.apache.org/tomcat-9.0-doc/config/valve.html#Semaphore_Valve (The Semaphore Valve is not Tomcat 9 specific, but was actually introduced in Tomcat 6). I experimented with this concept, and I found the following practical applications:
(Untested) The Semaphore Valve should be able to be nested within the Host element in the server.xml file.
(Tested) A [context-name].xml file can be placed inside [tomcat-home]/conf/Catalina/localhost with the valve nested within the Context element.
This is not necessarily the solution that I am going with, as more testing will need to be performed. However, I thought I'd add this as it is a potential answer to the problem.
Update:
As a recap, the SemaphoreValve was an option that was recommended to me through the Tomcat user mailing list as a solution to the issue that I described above. It turns out it was easier to implement than I anticipated. Adding the following to context.xml in the Tomcat/conf directory did the trick:
<Valve className="org.apache.catalina.valves.SemaphoreValve"
concurrency="10"
fairness="true" />
Thanks to Mark Thomas from the Apache group for supplying the solution.
Related
Our application accepts incoming requests (REST) and satisfies them using another of our services. When this application boots, it requests a number of connections from that other service - our goal is to maintain a 1:1, thread-to-connection, ratio (I won't get into why, its just that way).
Naturally, we want to define the number of threads/connections in one place, my thought is for the webapp to discover the "maxthreads" value as configured in server.xml -- without having to navigate to and parse the server.xml file. Is this possible?
Thanks
I'll answer my own question - JMX / MBeans.
I'm using JBoss EAP 5.1 and am connecting to remote EJBs, the java.naming.provider.url is set to:
corbaloc::server1:port,server2:port,server3:port,server4:port
How is this getting load balanced? It's not always going in first to last order is it? is it randomized some how?
That depends entirely on who provides the corbaloc: JNDI URL provider (there isn't one in JDK at least up to 1.6), but you're begging the question by describing it as 'load balancing'. It would be more accurate to describe it as 'failover'.
In a clustered Websphere environment you can have many multiple name servers to talk with in the form you describe.
About your question, here it mentions that:
You can specify the bootstrap addresses for all servers in the cluster in the URL. The operation succeeds if at least one of the servers is running, eliminating a single point of failure. There is no guarantee of any particular order in which the address list will be processed. For example, the second bootstrap address may be used to obtain the initial context even though the server at the first bootstrap address in the list is available.
I would like to totally disable session creation and management in my web app to eradicate the memory (and other resource) usage currently associated with Tomcat's standard session manager. This includes disabling sesison cookies and/or url rewriting as, if I'm succesful, there will be no sessions to track.
My web application has a single servlet that passes the xml it receives to an API/engine. This engine can run inside or outside a servlet container and it creates, tracks and manages sessions in its own way. I have zero need for the sessions in Tomcat and I'd like to reduce to the barest minimum the resources Tomcat uses for session management.
I ran some searches on the topic. The searches came up with some topics, including some on this website. It appears that the tightest way to address this issue is to create your own Manager implementation that, bascially, provides an 'empty' implementation that does the barest minimum. (There were some alternative suggestions but I found them to be relatively weak. These suggestions included "just don't call getSession()", and "set the 'cookies' attribute of a context to false". I think implementing a session manager that does what I want is better than these suggestions and it is the path I have elected to go down.)
Given this information, that rolling your own session manager is a good way to go, I then downloaded the Tomcat source code to take a look at code related to a Manager implementation. It all looks doable but it looks like a few hours work for me to come up with my attempt at a sesssion manager. Before committing to that path and the work involved, I thought I'd put it out there - Does anyone have a minimal session manager implementation for Tomcat they can share? One that does nothing would be best, but I'll take anything including tips and battle stories from anyone who has written their own session manager. I am working with Tomcat 6.
We have developed a JEE5 web application (WAR) and running it in production under WebLogic 11g (10.3.5).
Now the same application should be deployed as separate applications for different customers (different URLs, different data) on the same WebLogic.
I managed the first part by setting different context roots after deployment for each of them.
But I have yet to make them use different datasources - and since I want to avoid customer specific builds, the persistence.xml is the same for all applications, thus also the persistence unit name.
What is the best setup for this scenario? Am I forced making separate builds and by that different WARs or do I have to separate Managed Servers or Domains wihtin the server or is there a better way to solve it?
I know this thread is very old,but replying so that it may help someone with the same question stumbling on this thread.
The latest weblogic 12.2.1 comes with Multi-tenancy(add-on I guess) which can let you run same applications in a single domain.
Edit: Weblogic 12.2.1 introduced concept called Partitions. Partitions are both config and run-time subdivision of a weblogic Domain. In a single weblogic domain you can create multiple partitions. Each partition will have one or more resource groups. Resource groups are the logical grouping of weblogic resorces like data sources,jms,Java EE apps ,etc. For example to achieve what the original posts asked for , we create a Resource Group template with the web-application and the datasource as the resources. In the Data source configuration we can provide a place holder variable instead of actual URL as DB URL. Then we can create two partitions that refers to this Resource Group Template(Each partition will now have a separate web application and data source) . Each partition will override the DB URL property there by creating two data sources with same JNDI name.In each Partition we create virtual host/port so that the client can use that to access the application running in the respective partitions.
A better and more detailed information on this can be found in https://blogs.oracle.com/WebLogicServer/entry/domain_partitions_for_multi_tenancy
ServletContextListener.contextInitialized can look at the ServletContext and figure out which deployment is which
in web.xml, define a servlet context listener:
<listener>
<listener-class>com.path.YourServletContextListener</listener-class>
</listener>
and then in YourServletContextListener.java, add a contextInitialized method like this:
public void contextInitialized(ServletContextEvent sce)
{
ServletContext sc = sce.getServletContext();
String name = sc.getContextPath();
...
}
my thought is that you can use that name to select from multiple data sources that you have configured. depending on how you've been deployed, you'll make a different database connection and have the correct application's data.
It seems to me from what I saw in the Oracle documentation, that having several domains is the only way to separate data sources with the same persistence unit name - which is bad, since this basically means running two WLS in parallel.
For this reason I decided to go with building individual WAR files (which I tried to avoid initially), to include customer-specific persistence.xml files and specifying customer-specific datasources in the WLS.
I am developing application which is embedded within the cluster environment in Websphere AS. I am using several nodes and sometimes I would like to change configuration settings on the fly and propagate it to all nodes within the cluster. I don't want to hold the config in the db or at least I would like to cache it on the node level and trigger config refresh action which forces each node to refresh the config from some common ground (i.e. db or net drive)
to avoid constant round-trips to the config storage.
More over some configuration can't be stored in db i.e. log level needs to be applied on the logger object in each node separately.
I was thinking about using JMS Topics and publish/subscribe approach to achive that goal.
The idea is that each node could subscribe to each Topic and no matter which nodes initate the config change modification would be propagated to all nodes within the cluster.
Has anyone ever tried to do that in WAS and whether there are any obstacles with this approach. If there are or if you have any other suggestion on how to solve that problem I would be very greatfull for your help.
Tx in advance,
Marcin
Here are a few options to consider as alternatives to JMS -
Use Java EE environment entries. These are scoped to the application, and WAS will automatically propagate any changes to all servers against which the application is deployed. This is a good approach since it is the standard Java EE approach to application configuration, if it is robust enough to meet your use case.
Use a WebSphere Shared Library. This allows you to link your applications to static files external to your application (i.e. on the filesystem), such that they are available on your classpath. Although these files are located on the node file systems, there is a way that you can place these files in WebSphere's centralized configuration repository such that they are automatically propagated to all WAS nodes. For more details on this, see this answer.
Both of these options are optimized for static configuration; in other words, configuration settings that are intended to be set at assembly-time, deployment-time, or to be changed by system administrators, but they are not typically used for values that change frequently, nor are they generally changed programmatically at runtime. WAS does allow your applications to pick these configuration settings in a rolling fashion, such that no application downtime is required though.
Currently we solved the problem with maybe not the most pretty approach but with the most simple one. Since we are using only 2 nodes we have possibility to enter web interface of specific node where we modify settings per each node. Maybe it is not very pretty but for now it is the easiest way. The config is stored in DB and we are planning to trigger config reload in each node and change the log level per node as well.