Skip to content

Commit

Permalink
feat(perf): adapt policy for new classloader system (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
jhaeyaert authored Jan 6, 2022
1 parent 29f9dd6 commit 5e8a0b0
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 49 deletions.
71 changes: 35 additions & 36 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,17 @@ workflows:
- gravitee/d_pull_requests_secrets:
context: cicd-orchestrator
name: pr_secrets_resolution
# - gravitee/d_pr_tests_containers_qa:
# context: gravitee-qa
# name: process_pull_request_qa
# requires:
# - gravitee/d_pr_tests_containers_qa:
# context: gravitee-qa
# name: process_pull_request_qa
# requires:
# - pr_secrets_resolution
# # "What is the maven ID of the maven profile to use to build and deploy SNAPSHOTS to Prviate Artifactory ?"
# maven_profile_id: 'gio-dev'
# filters:
# # "What is the maven ID of the maven profile to use to build and deploy SNAPSHOTS to Prviate Artifactory ?"
# maven_profile_id: 'gio-dev'
# filters:
# branches:
# ignore:
# - master
# ignore:
# - master
- gravitee/d_pull_requests_ce:
name: process_pull_request
requires:
Expand All @@ -70,10 +70,10 @@ workflows:
# container_gun_image_name: 'openjdk'
# container_gun_image_tag: '11.0.3-jdk-stretch'
container_size: 'medium'
# filters:
# filters:
# branches:
# ignore:
# - master
# ignore:
# - master
# ---
# The 2 Workflows Below are there for the CICD Orchestrator to be able to
# release Gravitee Kubernetes in an APIM release Process, with Docker executors instead of VMs
Expand Down Expand Up @@ -197,13 +197,13 @@ workflows:
and:
- equal: [ standalone_release, << pipeline.parameters.gio_action >> ]
- not: << pipeline.parameters.dry_run >>
# ---
# Running the nexus staging makes sense only when the
# standalone release is being performed with dry run mode off
# That is to say, when the maven project is ready to be release to mmaven Staging
# Never the less, to test the CICD system, I temporarily git pushed a different configuration
# ---
# when:
# ---
# Running the nexus staging makes sense only when the
# standalone release is being performed with dry run mode off
# That is to say, when the maven project is ready to be release to mmaven Staging
# Never the less, to test the CICD system, I temporarily git pushed a different configuration
# ---
# when:
# equal: [ standalone_release, << pipeline.parameters.gio_action >> ]
jobs:
- gravitee/d_nexus_staging_secrets:
Expand Down Expand Up @@ -294,13 +294,13 @@ workflows:
and:
- equal: [ standalone_release_replay, << pipeline.parameters.gio_action >> ]
- not: << pipeline.parameters.dry_run >>
# ---
# Running the nexus staging makes sense only when the
# standalone release is being performed with dry run mode off
# That is to say, when the maven project is ready to be release to mmaven Staging
# Never the less, to test the CICD system, I temporarily git pushed a different configuration
# ---
# when:
# ---
# Running the nexus staging makes sense only when the
# standalone release is being performed with dry run mode off
# That is to say, when the maven project is ready to be release to mmaven Staging
# Never the less, to test the CICD system, I temporarily git pushed a different configuration
# ---
# when:
# equal: [ standalone_release, << pipeline.parameters.gio_action >> ]
jobs:
- gravitee/d_nexus_staging_secrets:
Expand Down Expand Up @@ -353,7 +353,6 @@ workflows:
maven_profile_id: << pipeline.parameters.maven_profile_id >>
s3_bucket_name: << pipeline.parameters.s3_bucket_name >>


# ---
# Nighlty for all CE repositories :
# builds the SNAPSHOT, and deploys
Expand All @@ -364,14 +363,14 @@ workflows:
nightly:
when:
equal: [ nightly, << pipeline.parameters.gio_action >> ]
# triggers:
# - schedule:
# cron: "0 0 * * *"
# filters:
# branches:
# only:
# - master
# - /^[0-999].[0-999].x/
# triggers:
# - schedule:
# cron: "0 0 * * *"
# filters:
# branches:
# only:
# - master
# - /^[0-999].[0-999].x/
jobs:
- gravitee/d_all_nightly_secrets:
context: cicd-orchestrator
Expand All @@ -389,4 +388,4 @@ workflows:
branches:
only:
- master
- /^[0-999].[0-999].x/
- /^[0-999].[0-999].x/
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

<maven-assembly-plugin.version>2.5.5</maven-assembly-plugin.version>
<freemarker.version>2.3.31</freemarker.version>
<guava.version>30.1.1-jre</guava.version>

<mockito.version>3.5.13</mockito.version>
</properties>
Expand Down Expand Up @@ -110,6 +111,13 @@
<scope>provided</scope>
</dependency>

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
<scope>provided</scope>
</dependency>

<!-- Test scope -->
<dependency>
<groupId>junit</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package io.gravitee.policy.metricsreporter;

import freemarker.cache.StringTemplateLoader;
import freemarker.core.TemplateClassResolver;
import freemarker.template.*;
import io.gravitee.gateway.api.ExecutionContext;
Expand All @@ -24,6 +23,7 @@
import io.gravitee.gateway.api.stream.ReadWriteStream;
import io.gravitee.policy.api.annotations.OnResponseContent;
import io.gravitee.policy.metricsreporter.configuration.MetricsReporterPolicyConfiguration;
import io.gravitee.policy.metricsreporter.freemarker.CustomTemplateLoader;
import io.gravitee.policy.metricsreporter.freemarker.LegacyDefaultMemberAccessPolicy;
import io.gravitee.policy.metricsreporter.metrics.AttributesBasedExecutionContext;
import io.gravitee.policy.metricsreporter.metrics.RequestMetrics;
Expand Down Expand Up @@ -62,7 +62,8 @@ public class MetricsReporterPolicy {

private final MetricsReporterPolicyConfiguration configuration;

private static final ConcurrentMap<String, HttpClient> clients = new ConcurrentHashMap<>();
private HttpClient client;
private static final CustomTemplateLoader templateLoader = new CustomTemplateLoader();
private static final Configuration templateConfiguration = loadConfiguration();

public MetricsReporterPolicy(
Expand Down Expand Up @@ -155,10 +156,17 @@ private void reportMetrics(ExecutionContext context) {
}

private HttpClient getOrCreateClient(ExecutionContext context) {
return clients.computeIfAbsent(
configuration.getUrl(),
url -> createClient(context)
);
if (client == null) {
// Synchronization should not occur more than few times in case of high throughput.
synchronized (this) {
// Avoid create multiple clients by double checking the client nullability.
if (client == null) {
client = createClient(context);
}
}
}

return client;
}

private HttpClient createClient(ExecutionContext context) {
Expand Down Expand Up @@ -204,19 +212,14 @@ private static Configuration loadConfiguration() {
configuration.setObjectWrapper(objectWrapperBuilder.build());

// Load inline templates
configuration.setTemplateLoader(new StringTemplateLoader());
configuration.setTemplateLoader(templateLoader);

return configuration;
}

Template getTemplate(String template) throws IOException {
StringTemplateLoader loader = (StringTemplateLoader) templateConfiguration.getTemplateLoader();
String hash = Sha1.sha1(template);
Object source = loader.findTemplateSource(hash);
if (source == null) {
loader.putTemplate(hash, template);
}

templateLoader.putIfAbsent(hash, template);
return templateConfiguration.getTemplate(hash);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/**
* Copyright (C) 2015 The Gravitee team (http://gravitee.io)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.gravitee.policy.metricsreporter.freemarker;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import freemarker.cache.TemplateLoader;
import java.io.Reader;
import java.io.StringReader;
import java.time.Duration;
import java.util.Objects;

// Duplicated class for now, see https://github.com/gravitee-io/issues/issues/6857
public class CustomTemplateLoader implements TemplateLoader {

/**
* Number of hours to keep script in cache after the last time it was accessed.
*/
private static final int CACHE_EXPIRATION_HOURS = 1;

/**
* Max number of entries in the cache.
*/
private static final int CACHE_MAXIMUM_SIZE = 1000;

private final Cache<Object, Object> templates = CacheBuilder
.newBuilder()
.maximumSize(CACHE_MAXIMUM_SIZE)
.expireAfterAccess(Duration.ofHours(CACHE_EXPIRATION_HOURS))
.build();

Cache<Object, Object> getCache() {
return templates;
}

@Override
public void closeTemplateSource(Object templateSource) {}

@Override
public Object findTemplateSource(String name) {
return templates.getIfPresent(name);
}

@Override
public long getLastModified(Object templateSource) {
return ((TemplateSource) templateSource).lastModified;
}

@Override
public Reader getReader(Object templateSource, String encoding) {
return new StringReader(((TemplateSource) templateSource).templateContent);
}

public void putIfAbsent(String name, String templateSource) {
if (templates.getIfPresent(name) == null) {
templates.put(
name,
new TemplateSource(name, templateSource, System.currentTimeMillis())
);
}
}

private static class TemplateSource {

private final String name;
private final String templateContent;
private final long lastModified;

TemplateSource(String name, String templateContent, long lastModified) {
this.name = name;
this.templateContent = templateContent;
this.lastModified = lastModified;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TemplateSource that = (TemplateSource) o;
return Objects.equals(name, that.name);
}

@Override
public int hashCode() {
return Objects.hash(name);
}

@Override
public String toString() {
return name;
}
}
}

0 comments on commit 5e8a0b0

Please sign in to comment.