Spring Service Garbage Collection - java

I have a Spring Service, which calls an API. This Service creates several objects and returns these to the client (of a REST request).
Is this good practice? I observe rising memory consumption with every request. Is there is no garbage collection happening?
#org.springframework.stereotype.Service("FanService")
public class Service {
private static final Logger log = LoggerFactory.getLogger(Service.class);
public List<String> allCLubsInLeague() {
try {
URI urlString = new URI("https://www.thesportsdb.com/api/v1/json/1/search_all_teams.php?l=German%20Bundesliga");
RestTemplate restTemplate = new RestTemplate();
TeamsList response = restTemplate.getForObject(urlString, TeamsList.class);
List<BundesligaTeams> bundesligaTeams = response.getTeams();
//ResponseEntity<List<BundesligaTeams>> test = t.getForEntity(urlString, BundesligaTeams.class);
List<String> teamList = new ArrayList<>();
bundesligaTeams.forEach(value -> teamList.add(value.getStrTeam()));
log.info(bundesligaTeams.get(0).getStrAlternate());
bundesligaTeams = null;
response = null;
urlString = null;
restTemplate = null;
return teamList;
} catch (Exception e) {
log.info(e.getMessage());
}
return null;
}
}

I don't see any memory leak in this code.
Your memory is raising in every request because Garbage Collector will garbage unused objects when it decides to do so. So your objects can be garbaged after 10 or 20 request - you never know.
This happens because you still have a lot of free memory on your heap so garbage collector is not forced to clean it up yet. If you will try to invoke many many requests you will see Garbage Collector activity soon.
If you want to see more details, you can always run jvisualvm which should be shipped with JDK and observe how your heap memory increase/decrease according to garbage collector activity

If you are not coding low-latency application with zero-garbage allocation you should focus on writing readable and maintainable code first. Only then tune performance if it's not acceptable.
It's ok to create objects if you have available memory, memory allocation is cheap comparing to a GET request. See Latency Numbers Every Programmer Should Know.
There is no reason to null a local variable unless you are trying to remove security credentials. Don't write bundesligaTeams = null; and other statements at the end, these object will be collected once they are not reachable.
RestTemplate should be a separate bean. Creating this object could be expensive if the underling HTTP client creation is expensive. Consider auto-wiring the default RestTemplate provided by Spring Boot.
Cache the result of the GET request locally if the data is not changing often. A list of all the clubs in the German Bundesliga will change only once a year.
You should avoid creating String for log.info() call if the info logging level is not enabled. Either use placeholder syntax or call log.isInfoEnabled() before. Check out the What is the fastest way of (not) logging? FAQ.

Related

Tomcat and garbage collecting database connections

I asked (and answered myself) this question a couple of days ago, and resolved the problem, but I can't quite understand why the problem was solved and was hoping to get some clarification.
Essentially, I have implemented a jax-rs-based REST service that retrieves information from a RavenDB database and returns that content in a stream. The problem that I had was an unclosed database results iterator, which caused the REST service to hang (and accept no further requests) after exactly 10 requests.
My code is, roughly, as follows:
public Response ...
{
(...)
StreamingOutput adminAreaStream = new StreamingOutput()
{
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
#Override
public void write(OutputStream output) throws IOException, WebApplicationException
{
try(IDocumentSession currentSession = ServiceListener.ravenDBStore.openSession())
{
Writer writer = new BufferedWriter(new OutputStreamWriter(output));
(...)
CloseableIterator<StreamResult<AdministrativeArea>> results;
(...)
writer.flush();
writer.close();
results.close();
currentSession.advanced().clear();
currentSession.close();
}
catch (Exception e)
{
System.out.println("Exception: " + e.getMessage() + e.getStackTrace());
}
}
};
if(!requestIsValid)
return Response.status(400).build();
else
return Response.ok(adminAreaStream).build();
}
From what I understand about the object lifecycle in Java, or rather more specifically object reachability and garbage collection, even though I didn't properly close that CleasableIterator, it should go out of scope/become unreachable by the time my method finishes with either a 400 or 200 status - and therefore get garbage collected.
Just to be clear: I am certainly not suggesting that one shouldn't properly close opened connections etc. - I AM doing that now - or rely on Java's garbage collection mechanism to save us from lazy/unclean coding... I am just struggling to understand exactly how those unclosed iterators could have caused the Tomcat behaviour observed.
In fact, my assumption is that we don't even need to know the details about the iterator's implementation, because at the "galactic level" of Java the object lifecycle, implementation differences are irrelevant. => "Once an object has become unreachable, it doesn't matter exactly how it was coded".
The only thing I can imagine is that Tomcat somehow, (through its container mechanism ?), slightly changes the game here, and causes things to "hang around".
Could someone please shed some light on this ?
Thanks in advance !
The CloseableIterator refers to a CloseableHttpResponse which refers to a HTTP connection. No finalizer releases the response or the connection, when CloseableIterator is not reachable anymore. You created a connection leak. Your bug is similar to the one described here: https://phillbarber.blogspot.com/2014/02/lessons-learned-from-connection-leak-in.html
See here why finalize methods to release resources are a bad idea: https://www.baeldung.com/java-finalize

Risks of using Apache CloseableHttpClient in a Singleton

I'm using Apache Http Client 4.5.3 and currently refactoring some code.
Currently I have a singleton Util that has several methods whose responsibility is to hit an API with gets, posts, patches, etc. Previously, we had been using an HttpClientBuilder to construct a CloseableHttpClient object for every call of every method. Roughly, the architecture for the Singleton is something like this:
import com.google.gson.Gson
import org.apache.http.client.methods.{HttpGet, HttpPost}
import org.apache.http.entity.StringEntity
import org.apache.http.impl.client.{CloseableHttpClient, HttpClientBuilder}
import org.apache.http.util.EntityUtils
import org.json4s.DefaultFormats
import org.json4s.jackson.JsonMethods.parse
object ApiCallerUtil {
case class StoreableObj(name:String, id:Long)
case class ResponseKey(key:Long)
def getKeyCall(param:String): ResponseKey = {
implicit val formats = DefaultFormats
val get = new HttpGet("http://wwww.someUrl.com/api/?value=" + param)
val client:CloseableHttpClient = HttpClientBuilder.create().build()
val response = client.execute(get)
try {
val entity = response.getEntity
val entityStr = EntityUtils.toString(entity)
parse(entityStr).extract[ResponseKey]
} finally {
response.close()
client.close()
}
}
def postNewObjCall(param:String, i:Long): Boolean = {
val post = new HttpPost(("http://wwww.someUrl.com/api/createNewObj"))
val client = HttpClientBuilder.create().build()
post.setHeader("Content-type", "application/json")
val pollAsJson = new Gson().toJson(StoreableObj(param, i))
post.setEntity(new StringEntity(pollAsJson))
val response = client.execute(post)
try {
if (response.getStatusLine.getStatusCode < 300) true else false
} finally {
response.close()
client.close()
}
}
//... and so on
}
Notes about how this is used - we have many classes all over our system that use this Singleton Util to make calls to the API. This Singleton will go through short periods of heavy use where several classes will hit the same calls with heavy frequency (up to #1000 of times within several minute periods), and also periods where it is hit several times over a long period of time (once or twice an hour), or not at all for hours at a time. Also, all the URLs it hits will start with the same URL (e.g. www.someUrl.com/api/)
But I'm wondering if it would make sense to implement it where the val client = HttpClientBuilder.create().build is called once as a private val for a in-object-only accessible variable. This way it is only created once, upon instantiation of the object. Here's where I pause, the Apache documentation does say these two things:
1.2.1. [Closeable]HttpClient implementations are expected to be thread safe. It is recommended that the same instance of this class is reused
for multiple request executions.
1.2.2. When an [Closeable]HttpClient instance is no longer needed and is about to go out of scope it is important to shut down its
connection manager to ensure that all connections kept alive by the
manager get closed and system resources allocated by those connections
are released.
I've read through most of the documentation, but don't have a solid answer to the following:
Are there any risks of having the CloseableHttpClient instance as private global variable? I'm worried something may get shut down if it's stale and that I'd have to resinstantiate it after a period of time, or, in the cases of heavy use, it would create too much of a bottleneck. Per the #1.2.2 above, the variable will "never" go out of scope, since it's a singleton object. But since I'm building just the client and passing it the HttpRequest objects as I go, and not connecting it to the API outside of the request alone, it seems it shouldn't matter.
Due to the nature of how this ApiCallerUtil Singleton is used, would it be wise to perhaps make use of their HttpClientConnectionManager or. PoolingHttpClientConnectionManager to maintain a steady connection to www.someUrl.com/api/? Will the performance increase be worth it? So far, the current implementation doesn't seem to have any drastic performance drawbacks.
Thanks for any feedback!
There are none (based on my 15+ years of experience with HttpClient).
This really depends on various factors (overhead of TLS session handshake, and so on). I imagine one would really want to ensure that series of related requests get executed over a persistent connection. During an extended period of inactivity one may want to evict all idle connections from the connection pool. This has an added benefit of reducing the chance of running into a stale (half-closed) connection problem.

Blocking vs Non-Blocking - Performance Differences

I am responsible for implementing a Websocket Endpoint, whose sequence of flow is like this:
Check if the request is valid.
If valid, hit another backend service for analysis.
Once the response is received, convert into a specific structure and return to client.
The websocket service is written in Java using Spring 4 and running on Tomcat 8.5. I am using default connector in Tomcat.
I had two options:
Option 1 - Hit the backend service in a blocking manner.
HttpRequest request = Unirest.get(url).queryString(params);
HttpResponse<String> response = request.asString();
//return response to client.
Option 2 - Hit the backend service in a non-blocking manner.
HttpRequest request = Unirest.get(url).queryString(params);
request.asStringAsync(new Callback<String>() {
#Override
public void failed(UnirestException e) {}
#Override
public void completed(HttpResponse<String> response) {
String result = response.getBody().toString();
// return result to client
});
The average response time from the backend service is always ~400ms.
I load testing the application in "blocking" as well as "non-blocking" modes. To my surprise, the results were bit different from my expectations:
The average response time of "non-blocking" approach was slightly lower than the "blocking" approach.
There were substantially more errors in the "non-blocking" implementation than "blocking" (connection, timeout errors).
Garbage collection was working overtime to clear objects in "non-blocking" implementation with high spikes in JVisualVM. GC performance was much more smooth in blocking implementation.
Results suggest that I should be using blocking approach instead of non-blocking. Am I missing anything?
CPU Usage and Throughput is a major difference between blocking and Non-Blocking system, for more information please refer this.
https://www.linkedin.com/pulse/differences-between-blocking-vs-non-blocking-systems-ashish-modi

Tomee WebContext not releasing CreationalContexts

I'm experiencing a quite aggressive memory leak using Tomee, Apache Open Web Beans and JSF.
The following code in org.apache.openejb.core.WebContext is continually adding elements every time we navigate to a page but never removes them:
if (webBeansContext != null) {
final InjectionTargetBean<Object> bean = InjectionTargetBean.class.cast(beanDefinition);
bean.getInjectionTarget().inject(beanInstance, creationalContext);
creatonalContexts.put(beanInstance, creationalContext);
}
Resulting in a massive map of JSF Objects and their relating CreationalContext which is never garbage collected:
Ultimately this is causing the server to run out of memory and fall over. Has anybody encountered this?

Are there major scaling limits with play framework and jdbc blocking io calls

I am using the playframework (2.4) for Java and connecting it to Postgres. The play framework is being used as a restful service and all it is doing is insert,updates,reads and deletes using JDBC. On this play page https://www.playframework.com/documentation/2.3.x/JavaAsync it states clearly that JDBC is blocking and that play has few threads. For the people who know about this, how limiting could this be and is there some way I can work around this? My specific app can have a few hundred database calls per second. I will have all the hardware and extra servers but do not know how play can handle this or scale to handle this in the code. My code in play looks like this:
public static Result myprofile() {
DynamicForm requestData = Form.form().bindFromRequest();
Integer id = Integer.parseInt(requestData.get("id"));
try {
JSONObject jo = null;
Connection conn = DB.getConnection();
ResultSet rs;
JSONArray ja = new JSONArray();
PreparedStatement ps = conn.prepareStatement("SELECT p.fullname as fullname, s.post as post,to_char(s.created_on, 'MON DD,YYYY') as created_on,s.last_reply as last_reply,s.id as id,s.comments as comments,s.state as state,s.city as city,s.id as id FROM profiles as p INNER JOIN streams as s ON (s.profile_id=p.id) WHERE s.profile_id=? order by created_on desc");
ps.setInt(1, id);
rs = ps.executeQuery();
while (rs.next()) {
jo = new JSONObject();
jo.put("fullname", rs.getString("fullname"));
jo.put("post", rs.getString("post"));
jo.put("city", rs.getString("city"));
jo.put("state", rs.getString("state"));
jo.put("comments", rs.getInt("comments"));
jo.put("id", rs.getInt("id"));
jo.put("last_reply", difference(rs.getInt("last_reply"), rs.getString("created_on")));
ja.put(jo);
}
JSONObject mainObj = new JSONObject();
mainObj.put("myprofile", ja);
String total = mainObj.toString();
System.err.println(total);
conn.close();
return ok(total);
} catch (Exception e) {
e.getMessage();
}
return ok();
}
I also know that I can try to wrap that in a futures promise however the blocking still occurs. As stated before I will have all the servers and the other stuff taken care of, but would the play framework be able to scale to hundreds of requests per second using jdbc? I am asking and learning now to avoid serious mistakes later on.
Play can absolutely handle this load.
The documentation states that blocking code should be avoided inside controller methods - the default configuration is tuned for them to have asynchronous execution. If you stick some blocking calls in there, your controller will now be waiting for that call to finish before it can process another incoming request - this is bad.
You can’t magically turn synchronous IO into asynchronous by wrapping
it in a Promise. If you can’t change the application’s architecture to
avoid blocking operations, at some point that operation will have to
be executed, and that thread is going to block. So in addition to
enclosing the operation in a Promise, it’s necessary to configure it
to run in a separate execution context that has been configured with
enough threads to deal with the expected concurrency. See
Understanding Play thread pools for more information.
https://www.playframework.com/documentation/2.4.x/JavaAsync#Make-controllers-asynchronous
I believe you are aware of this but I wanted to point out the bolded section. Your database has a limited number of threads that are available for applications to make calls on - it may be helpful to track this number down, create a new execution context that is turned for these threads, and assign that new execution context to a promise that wraps your database call.
Check out this post about application turning for Play, it should give you an idea of what this looks like. I believe he is using Akka Actors, something that might be out of scope for you, but the idea for thread tuning is the same:
Play 2 is optimized out-of-the-box for HTTP requests which don’t
contain blocking calls (i.e. asynchronous). Most database-driven apps
in Java use synchronous calls via JDBC so Play 2 needs a bit of extra
configuration to tune Akka for these types of requests.
http://www.jamesward.com/2012/06/25/optimizing-play-2-for-database-driven-apps
If you try to execute a massive number of requests on the database without turning the threads, you run the risk of starving the rest of your application of threads, which will halt your application. For the load you are expecting, the default tuning might be ok, but it is worth performing some additional investigating.
Getting started with thread tuning:
https://www.playframework.com/documentation/2.4.x/ThreadPools
You should update your controller to return Promise and there is also no reason to make it static anymore with Play 2.4. https://www.playframework.com/documentation/2.4.x/Migration24#Routing
Define an execution context in the application.conf with name "jdbc-execution-context"
//reference to context
ExecutionContext jdbcExecutionContext = Akka.system().dispatchers()
.lookup("jdbc-execution-context");
return promise(() -> {
//db call
}, jdbcExecutionContext)
.map(callResult -> ok(callResult));

Categories