mirror of https://github.com/dapr/java-sdk.git
				
				
				
			Fix high mem usage due to many OkHttpClient instances. (#373)
This commit is contained in:
		
							parent
							
								
									604eff8cd4
								
							
						
					
					
						commit
						eb7763f126
					
				|  | @ -9,6 +9,7 @@ import io.dapr.config.Properties; | |||
| import okhttp3.OkHttpClient; | ||||
| 
 | ||||
| import java.time.Duration; | ||||
| import java.util.concurrent.atomic.AtomicReference; | ||||
| 
 | ||||
| /** | ||||
|  * A builder for the DaprHttp. | ||||
|  | @ -16,21 +17,30 @@ import java.time.Duration; | |||
| public class DaprHttpBuilder { | ||||
| 
 | ||||
|   /** | ||||
|    * Read timeout for http calls. | ||||
|    * Singleton OkHttpClient. | ||||
|    */ | ||||
|   private static final Duration DEFAULT_READ_TIMEOUT = Duration.ofSeconds(60); | ||||
|   private static final AtomicReference<OkHttpClient> OK_HTTP_CLIENT = new AtomicReference<>(); | ||||
| 
 | ||||
|   /** | ||||
|    * Static lock object. | ||||
|    */ | ||||
|   private static final Object LOCK = new Object(); | ||||
| 
 | ||||
|   /** | ||||
|    * Read timeout used to build object. | ||||
|    */ | ||||
|   private Duration readTimeout = DEFAULT_READ_TIMEOUT; | ||||
|   private Duration readTimeout = Duration.ofSeconds(Properties.HTTP_CLIENT_READTIMEOUTSECONDS.get()); | ||||
| 
 | ||||
|   /** | ||||
|    * Sets the read timeout duration for the instance to be built. | ||||
|    * | ||||
|    * <p>Instead, set environment variable "DAPR_HTTP_CLIENT_READTIMEOUTSECONDS", | ||||
|    *   or system property "dapr.http.client.readtimeoutseconds". | ||||
|    * | ||||
|    * @param duration Read timeout duration. | ||||
|    * @return Same builder instance. | ||||
|    */ | ||||
|   @Deprecated | ||||
|   public DaprHttpBuilder withReadTimeout(Duration duration) { | ||||
|     this.readTimeout = duration; | ||||
|     return this; | ||||
|  | @ -52,9 +62,17 @@ public class DaprHttpBuilder { | |||
|    * @return Instance of {@link DaprHttp} | ||||
|    */ | ||||
|   private DaprHttp buildDaprHttp() { | ||||
|     if (OK_HTTP_CLIENT.get() == null) { | ||||
|       synchronized (LOCK) { | ||||
|         if (OK_HTTP_CLIENT.get() == null) { | ||||
|           OkHttpClient.Builder builder = new OkHttpClient.Builder(); | ||||
|           builder.readTimeout(this.readTimeout); | ||||
|           OkHttpClient okHttpClient = builder.build(); | ||||
|     return new DaprHttp(Properties.SIDECAR_IP.get(), Properties.HTTP_PORT.get(), okHttpClient); | ||||
|           OK_HTTP_CLIENT.set(okHttpClient); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     return new DaprHttp(Properties.SIDECAR_IP.get(), Properties.HTTP_PORT.get(), OK_HTTP_CLIENT.get()); | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -38,6 +38,11 @@ public class Properties { | |||
|    */ | ||||
|   private static final Charset DEFAULT_STRING_CHARSET = StandardCharsets.UTF_8; | ||||
| 
 | ||||
|   /** | ||||
|    * Dapr's default timeout in seconds for HTTP client reads. | ||||
|    */ | ||||
|   private static final Integer DEFAULT_HTTP_CLIENT_READTIMEOUTSECONDS = 60; | ||||
| 
 | ||||
|   /** | ||||
|    * IP for Dapr's sidecar. | ||||
|    */ | ||||
|  | @ -86,4 +91,12 @@ public class Properties { | |||
|       "DAPR_STRING_CHARSET", | ||||
|       DEFAULT_STRING_CHARSET, | ||||
|       (s) -> Charset.forName(s)); | ||||
| 
 | ||||
|   /** | ||||
|    * Dapr's timeout in seconds for HTTP client reads. | ||||
|    */ | ||||
|   public static final Property<Integer> HTTP_CLIENT_READTIMEOUTSECONDS = new IntegerProperty( | ||||
|       "dapr.http.client.readtimeoutseconds", | ||||
|       "DAPR_HTTP_CLIENT_READTIMEOUTSECONDS", | ||||
|       DEFAULT_HTTP_CLIENT_READTIMEOUTSECONDS); | ||||
| } | ||||
|  |  | |||
|  | @ -9,37 +9,26 @@ import okhttp3.OkHttpClient; | |||
| import org.junit.Test; | ||||
| 
 | ||||
| import java.lang.reflect.Field; | ||||
| import java.time.Duration; | ||||
| 
 | ||||
| import static org.junit.Assert.assertEquals; | ||||
| import static org.junit.Assert.assertNotNull; | ||||
| import static org.junit.Assert.assertSame; | ||||
| 
 | ||||
| public class DaprHttpBuilderTest { | ||||
| 
 | ||||
|   @Test | ||||
|   public void withReadTimeout() throws Exception { | ||||
|     DaprHttpBuilder daprHttpBuilder = new DaprHttpBuilder(); | ||||
|     Duration duration = Duration.ofSeconds(999); | ||||
|     daprHttpBuilder.build(); | ||||
|     DaprHttpBuilder dapr = daprHttpBuilder.withReadTimeout(duration); | ||||
|     assertNotNull(dapr); | ||||
|   public void singletonOkHttpClient() throws Exception { | ||||
|     DaprHttp daprHttp = new DaprHttpBuilder().build(); | ||||
|     DaprHttp anotherDaprHttp = new DaprHttpBuilder().build(); | ||||
| 
 | ||||
|     DaprHttp daprHttp = daprHttpBuilder.build(); | ||||
|     assertOKHttpPropertyValue(daprHttp, "readTimeoutMillis", (int)duration.toMillis()); | ||||
|     assertSame(getOkHttpClient(daprHttp), getOkHttpClient(anotherDaprHttp)); | ||||
|   } | ||||
| 
 | ||||
|   private static final void assertOKHttpPropertyValue(DaprHttp daprHttp, String propertyName, Object expectedValue) throws Exception { | ||||
|     // First, get okHttpClient. | ||||
|   private static OkHttpClient getOkHttpClient(DaprHttp daprHttp) throws Exception { | ||||
|     Field httpClientField = DaprHttp.class.getDeclaredField("httpClient"); | ||||
|     httpClientField.setAccessible(true); | ||||
|     OkHttpClient okHttpClient = (OkHttpClient) httpClientField.get(daprHttp); | ||||
|     assertNotNull(okHttpClient); | ||||
| 
 | ||||
|     Field propertyField = OkHttpClient.class.getDeclaredField(propertyName); | ||||
|     propertyField.setAccessible(true); | ||||
|     Object value = propertyField.get(okHttpClient); | ||||
|     assertNotNull(value); | ||||
|     assertEquals(expectedValue, value); | ||||
|     return okHttpClient; | ||||
|   } | ||||
| 
 | ||||
| } | ||||
		Loading…
	
		Reference in New Issue