diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RateLimiter.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RateLimiter.java new file mode 100644 index 00000000000..809303043c4 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RateLimiter.java @@ -0,0 +1,34 @@ +package org.apache.hadoop.yarn.server.resourcemanager.webapp; + +import com.google.common.base.Throwables; + +class RateLimiter { + + private final int recoveryMillis; + private long lastAcquired = 0L; + private final Object lock = new Object(); + + private RateLimiter(int recoveryMillis) { + this.recoveryMillis = recoveryMillis; + } + + public static RateLimiter withRecoveryMilliSeconds(int recoveryMillis) { + return new RateLimiter(recoveryMillis); + } + + public void acquire() { + synchronized (this.lock) { + long ts = System.currentTimeMillis(); + long elapsed = ts - lastAcquired; + if (elapsed < recoveryMillis) { + try { + Thread.sleep(recoveryMillis - elapsed); + } catch (InterruptedException e) { + throw Throwables.propagate(e); + } + } + lastAcquired = ts; + } + } + +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesDelegationTokenAuthentication.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesDelegationTokenAuthentication.java index b406fdbf0e9..49b1c16cfd5 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesDelegationTokenAuthentication.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesDelegationTokenAuthentication.java @@ -316,6 +316,10 @@ public void testDelegationTokenOps() throws Exception { // The request shouldn't work when authenticated using DelegationTokens @Test public void testDoAs() throws Exception { + // Using a ratelimiter for webservice calls, to prevent intermittent + // "KrbException: Request is a replay (34)" exception, which happens when + // the same principal issues too many requests within a small time interval + final RateLimiter rateLimiter = RateLimiter.withRecoveryMilliSeconds(1000); KerberosTestUtils.doAsClient(new Callable() { @Override @@ -326,6 +330,7 @@ public Void call() throws Exception { String body = "{\"renewer\":\"" + renewer + "\"}"; URL url = new URL("http://localhost:8088/ws/v1/cluster/delegation-token?doAs=client2"); + rateLimiter.acquire(); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); setupConn(conn, "POST", MediaType.APPLICATION_JSON, body); InputStream response = conn.getInputStream(); @@ -354,12 +359,14 @@ public Void call() throws Exception { } }); + rateLimiter.acquire(); // this should not work final String token = getDelegationToken("client"); String renewer = "renewer"; String body = "{\"renewer\":\"" + renewer + "\"}"; URL url = new URL("http://localhost:8088/ws/v1/cluster/delegation-token?doAs=client2"); + rateLimiter.acquire(); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty(delegationTokenHeader, token); setupConn(conn, "POST", MediaType.APPLICATION_JSON, body); @@ -381,6 +388,7 @@ public Void call() throws Exception { new URL( "http://localhost:8088/ws/v1/cluster/delegation-token?doAs=client"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); + rateLimiter.acquire(); setupConn(conn, "POST", MediaType.APPLICATION_JSON, body); try { conn.getInputStream();