স্প্রিং বুট ক্লায়েন্টের পারফরম্যান্স উন্নত করা একটি গুরুত্বপূর্ণ বিষয়, বিশেষ করে মাইক্রোসার্ভিস আর্কিটেকচারের ক্ষেত্রে যেখানে ক্লায়েন্ট সার্ভিসগুলোর মধ্যে কমিউনিকেশন অত্যন্ত গুরুত্বপূর্ণ। এখানে Spring Boot ক্লায়েন্টের (RestTemplate/WebClient) পারফরম্যান্স অপটিমাইজ করার কিছু কৌশল আলোচনা করা হলো।
Spring Boot এর ডিফল্ট HTTP ক্লায়েন্ট হলো HttpURLConnection, যা সীমিত পারফরম্যান্স প্রদান করে। HTTP ক্লায়েন্টের পারফরম্যান্স উন্নত করতে নিচের কোনো একটি ক্লায়েন্ট ব্যবহার করুন:
কনফিগারেশন:
@Bean
public WebClient webClient() {
HttpClient httpClient = HttpClient.create()
.responseTimeout(Duration.ofSeconds(5))
.doOnConnected(conn ->
conn.addHandlerLast(new ReadTimeoutHandler(5))
.addHandlerLast(new WriteTimeoutHandler(5))
);
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
HTTP কলের প্রতিটি রিকোয়েস্ট-রেসপন্সের জন্য নতুন কানেকশন তৈরি করা ব্যয়বহুল। Connection Pooling ব্যবহার করে কানেকশন পুনরায় ব্যবহার করুন।
@Bean
public RestTemplate restTemplate() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setHttpClient(HttpClients.custom()
.setMaxConnTotal(100)
.setMaxConnPerRoute(20)
.build());
return new RestTemplate(factory);
}
@Bean
public WebClient webClientWithConnectionPool() {
HttpClient httpClient = HttpClient.create()
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000)
.doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(5))
.addHandlerLast(new WriteTimeoutHandler(5)))
.connectionProvider(ConnectionProvider.builder("custom")
.maxConnections(100)
.maxIdleTime(Duration.ofSeconds(20))
.build());
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
@Bean
public RestTemplate restTemplateWithTimeout() {
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
factory.setConnectTimeout(5000);
factory.setReadTimeout(5000);
return new RestTemplate(factory);
}
HttpClient httpClient = HttpClient.create()
.responseTimeout(Duration.ofSeconds(5));
অপ্রয়োজনীয় API কল এড়াতে Spring Cache ব্যবহার করতে পারেন। Spring Boot এর ক্যাশিং এনাবল করতে:
Dependency যোগ করুন:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
Cache Configuration:
@EnableCaching
@Configuration
public class CacheConfig {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("responses");
}
}
Cache ব্যবহার:
@Cacheable("responses")
public String getCachedData(String url) {
return restTemplate.getForObject(url, String.class);
}
Spring Cloud LoadBalancer ব্যবহার করে সার্ভিস ডিসকভারি এবং লোড ব্যালেন্সিং নিশ্চিত করুন।
@Bean
@LoadBalanced
public RestTemplate loadBalancedRestTemplate() {
return new RestTemplate();
}
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder() {
return WebClient.builder();
}
Response সাইজ কমানোর জন্য Gzip ব্যবহার করুন। WebClient বা RestTemplate এ হেডার যোগ করুন:
webClient.get()
.uri("/api/data")
.header("Accept-Encoding", "gzip")
.retrieve()
.bodyToMono(String.class);
সার্ভিস ফেইল হলে API কল বন্ধ করতে Circuit Breaker ব্যবহার করুন।
Dependency যোগ করুন:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
</dependency>
Usage:
@CircuitBreaker(name = "myService", fallbackMethod = "fallback")
public String callService() {
return restTemplate.getForObject("http://example.com/api", String.class);
}
public String fallback(Exception e) {
return "Fallback response";
}
API কলের পারফরম্যান্স মনিটর করতে Spring Boot Actuator এবং Micrometer ব্যবহার করুন।
Dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Schedulers.parallel();
Schedulers.boundedElastic();
Spring Boot ক্লায়েন্টের পারফরম্যান্স অপটিমাইজ করতে নিচের বিষয়গুলোর দিকে গুরুত্ব দিন:
প্রয়োজনে আরও বিস্তারিত বা নির্দিষ্ট উদাহরণ চাইলে জানাতে পারেন! 😊
Spring Boot ক্লায়েন্টে RestTemplate
এবং WebClient
RESTful API কল করতে ব্যবহৃত হয়। তবে এদের ব্যবহার করার সময় কিছু পারফরম্যান্স ইস্যু দেখা দিতে পারে, যা অ্যাপ্লিকেশনের কার্যকারিতা এবং রেসপন্স টাইম প্রভাবিত করে। এখানে RestTemplate
এবং WebClient
-এর পারফরম্যান্স সম্পর্কিত ইস্যু এবং সেগুলো সমাধানের পদ্ধতি আলোচনা করা হলো:
RestTemplate
একটি ব্লকিং HTTP ক্লায়েন্ট। এটি সিঙ্ক্রোনাস পদ্ধতিতে কাজ করে এবং রেসপন্স না আসা পর্যন্ত থ্রেড আটকে রাখে। এই কারণে থ্রেড সংখ্যা বেশি হলে পারফরম্যান্স ড্রপ হয়।RestTemplate
পরিবর্তে WebClient
ব্যবহার করা উচিত।RestTemplate
প্রতি অনুরোধে একটি থ্রেড ব্যবহার করে। যদি অনেক অনুরোধ হয়, তবে থ্রেড পুল দ্রুত পূর্ণ হয়ে যায়।ThreadPoolTaskExecutor
বা ExecutorService
ব্যবহার করে কনফিগার করা যায়।HttpComponentsClientHttpRequestFactory
ব্যবহার করুন।import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(100); // সর্বোচ্চ কানেকশন সংখ্যা
connectionManager.setDefaultMaxPerRoute(20); // প্রতি রুটের জন্য সর্বোচ্চ কানেকশন সংখ্যা
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(factory);
}
}
RestTemplate
বড় স্কেল অ্যাপ্লিকেশন বা মাইক্রোসার্ভিসের জন্য উপযুক্ত নয়। থ্রেড-ব্লকিং এর কারণে এটি বেশি লোড পরিচালনা করতে পারে না।WebClient
ব্যবহার করুন।WebClient
ব্যবহার করার জন্য সঠিক কনফিগারেশন প্রয়োজন। ডিফল্ট সেটিংস যথেষ্ট কার্যকর নয়।import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import java.time.Duration;
@Configuration
public class WebClientConfig {
@Bean
public WebClient webClient() {
HttpClient httpClient = HttpClient.create()
.responseTimeout(Duration.ofSeconds(5)) // টাইমআউট সেট করুন
.doOnConnected(conn ->
conn.addHandlerLast(new ReadTimeoutHandler(5))
.addHandlerLast(new WriteTimeoutHandler(5)));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
}
WebClient
নতুন কানেকশন তৈরি করে। এটি কানেকশন পুলিং চালু না করলে পারফরম্যান্সে নেতিবাচক প্রভাব ফেলে।import reactor.netty.resources.ConnectionProvider;
HttpClient httpClient = HttpClient.create(
ConnectionProvider.builder("custom")
.maxConnections(50) // সর্বোচ্চ কানেকশন সংখ্যা
.pendingAcquireTimeout(Duration.ofSeconds(5)) // Pending timeout
.build()
);
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
buffer
এড়িয়ে stream
ব্যবহার করুন।Flux
ব্যবহার করে স্ট্রিম ডেটা প্রক্রিয়াকরণ করুন।public Flux<String> fetchLargeData(String url) {
return webClient.get()
.uri(url)
.retrieve()
.bodyToFlux(String.class); // ডেটা স্ট্রিম আকারে প্রসেসিং
}
WebClient
টাইমআউট কনফিগার করা থাকে না, যা অপ্রয়োজনীয় বিলম্ব সৃষ্টি করতে পারে।HttpClient httpClient = HttpClient.create()
.responseTimeout(Duration.ofSeconds(5)); // রেসপন্স টাইমআউট
WebClient webClient = WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
ফিচার | RestTemplate | WebClient |
---|---|---|
Nature | Blocking | Non-blocking |
Concurrency | Low | High |
Scalability | Limited | Highly scalable |
Configuration | Simple | Requires proper configuration |
Use Case | Legacy or simple synchronous apps | Modern, reactive, and scalable apps |
স্প্রিং বুট ক্লায়েন্টে Connection Pooling এবং Timeout কনফিগারেশন কার্যকর করতে RestTemplate
বা WebClient
ব্যবহার করা যেতে পারে। নিচে ধাপে ধাপে এই কনফিগারেশনগুলো দেখানো হলো।
HttpClient
বা HttpComponentsClientHttpRequestFactory
ব্যবহার করে Connection Pooling সেটআপ করা যায়।
pom.xml
এ Apache HttpClient ডিপেন্ডেন্সি যোগ করুন:
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.4</version>
</dependency>
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
import org.apache.hc.core5.util.TimeValue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
// Create connection manager
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(50); // Max total connections
connectionManager.setDefaultMaxPerRoute(20); // Max connections per route
connectionManager.setValidateAfterInactivity(TimeValue.ofSeconds(10));
// Create HttpClient with connection manager
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
// Create RestTemplate with custom request factory
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(requestFactory);
}
}
Reactor Netty
ব্যবহার করে WebClient এ Connection Pooling কনফিগার করা যায়।
<dependency>
<groupId>io.projectreactor.netty</groupId>
<artifactId>reactor-netty</artifactId>
</dependency>
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
@Configuration
public class WebClientConfig {
@Bean
public WebClient webClient() {
// Create connection pool
ConnectionProvider provider = ConnectionProvider.builder("custom")
.maxConnections(50)
.pendingAcquireMaxCount(100)
.build();
HttpClient httpClient = HttpClient.create(provider);
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
}
HttpComponentsClientHttpRequestFactory
ব্যবহার করে Timeout কনফিগার করা যায়।
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.util.Timeout;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
CloseableHttpClient httpClient = HttpClients.custom()
.setDefaultRequestConfig(
org.apache.hc.client5.http.config.RequestConfig.custom()
.setConnectTimeout(Timeout.ofSeconds(5)) // Connection timeout
.setResponseTimeout(Timeout.ofSeconds(10)) // Read timeout
.build()
)
.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(requestFactory);
}
}
HttpClient
ব্যবহার করে WebClient-এ Timeout কনফিগার করা যায়।
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;
import reactor.netty.resources.ConnectionProvider;
@Configuration
public class WebClientConfig {
@Bean
public WebClient webClient() {
HttpClient httpClient = HttpClient.create()
.responseTimeout(java.time.Duration.ofSeconds(10)) // Response timeout
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000); // Connection timeout
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
}
@Bean
public RestTemplate restTemplate() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(50);
connectionManager.setDefaultMaxPerRoute(20);
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(
org.apache.hc.client5.http.config.RequestConfig.custom()
.setConnectTimeout(Timeout.ofSeconds(5))
.setResponseTimeout(Timeout.ofSeconds(10))
.build()
)
.build();
return new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient));
}
@Bean
public WebClient webClient() {
ConnectionProvider provider = ConnectionProvider.builder("custom")
.maxConnections(50)
.pendingAcquireMaxCount(100)
.build();
HttpClient httpClient = HttpClient.create(provider)
.responseTimeout(java.time.Duration.ofSeconds(10))
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000);
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(httpClient))
.build();
}
PoolingHttpClientConnectionManager
ব্যবহার।ConnectionProvider
ব্যবহার।এই পদ্ধতিগুলো ব্যবহার করে আপনি স্প্রিং বুট ক্লায়েন্টে Connection Pooling এবং Timeout সঠিকভাবে কনফিগার করতে পারবেন।
Spring Boot Client এ Caching এবং Rate Limiting ব্যবহার করে পারফরম্যান্স অপ্টিমাইজেশন করা অত্যন্ত কার্যকর পদ্ধতি। Caching পুনরাবৃত্ত রিকোয়েস্টের প্রতিক্রিয়া দ্রুত প্রদান করতে ব্যবহৃত হয়, এবং Rate Limiting সার্ভারের উপর অতিরিক্ত লোড পড়া থেকে রক্ষা করে। নিচে এই দুটি পদ্ধতি বিস্তারিতভাবে ব্যাখ্যা করা হয়েছে:
Caching ব্যবহার করে ক্লায়েন্ট API রেসপন্সগুলো মেমোরি বা স্টোরেজে সংরক্ষণ করে। একবার ডেটা ক্যাশে সংরক্ষিত হলে, একই রিকোয়েস্টের জন্য সার্ভারে না গিয়ে ক্যাশ থেকে দ্রুত রেসপন্স প্রদান করা যায়।
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
Application Class এ @EnableCaching
এনোটেশন যোগ করুন:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
@SpringBootApplication
@EnableCaching
public class SpringBootClientApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootClientApplication.class, args);
}
}
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class ApiService {
private final RestTemplate restTemplate = new RestTemplate();
@Cacheable("apiData")
public String fetchData() {
String url = "https://api.example.com/data";
System.out.println("Fetching data from API...");
return restTemplate.getForObject(url, String.class);
}
}
application.yml ফাইল:
spring:
cache:
type: simple # Simple in-memory cache
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
@Service
public class CacheService {
@CacheEvict(value = "apiData", allEntries = true)
public void clearCache() {
System.out.println("Cache cleared!");
}
}
Rate Limiting এমন একটি পদ্ধতি যা নির্দিষ্ট সময়ে API রিকোয়েস্টের সংখ্যা সীমাবদ্ধ করে। এটি সার্ভারের অতিরিক্ত লোড এড়াতে সহায়ক।
<dependency>
<groupId>com.github.bucket4j</groupId>
<artifactId>bucket4j-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Rate Limiter Filter তৈরি করুন:
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Bucket4j;
import io.github.bucket4j.Refill;
import org.springframework.stereotype.Component;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.Duration;
@Component
public class RateLimiterFilter extends javax.servlet.Filter {
private final Bucket bucket;
public RateLimiterFilter() {
Bandwidth limit = Bandwidth.classic(5, Refill.greedy(5, Duration.ofMinutes(1)));
this.bucket = Bucket4j.builder().addLimit(limit).build();
}
@Override
public void doFilter(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
if (bucket.tryConsume(1)) {
chain.doFilter(request, response);
} else {
response.setStatus(HttpServletResponse.SC_TOO_MANY_REQUESTS);
response.getWriter().write("Too Many Requests");
}
}
}
Filter Bean Configure করুন:
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class RateLimiterConfig {
@Bean
public FilterRegistrationBean<RateLimiterFilter> rateLimiterFilter() {
FilterRegistrationBean<RateLimiterFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new RateLimiterFilter());
registrationBean.addUrlPatterns("/api/*"); // Apply on specific API endpoints
return registrationBean;
}
}
Spring Boot ক্লায়েন্টে Caching এবং Rate Limiting একত্রে ব্যবহার করে ক্লায়েন্ট এবং সার্ভারের মধ্যে ভারসাম্য বজায় রাখা যায়।
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class OptimizedApiService {
private final RestTemplate restTemplate = new RestTemplate();
@Cacheable("optimizedData")
public String fetchData() {
String url = "https://api.example.com/data";
System.out.println("Fetching data from API...");
return restTemplate.getForObject(url, String.class);
}
}
Fetching data from API... # First request
# Second request returns cached data, no "Fetching data" log
Response: 200 OK # First 5 requests
Response: 429 Too Many Requests # Subsequent requests in the same minute
Caching এবং Rate Limiting একত্রে ব্যবহার করে Spring Boot Client অ্যাপ্লিকেশন আরও স্থিতিশীল এবং পারফরম্যান্স-উন্নত করা সম্ভব।
স্প্রিং বুট ক্লায়েন্টে Performance Optimization করার জন্য বিভিন্ন পদ্ধতি ব্যবহার করা যায়। এর মধ্যে রয়েছে caching, asynchronous processing, connection pooling, এবং efficient data serialization। নিচে উদাহরণসহ একটি পূর্ণাঙ্গ গাইড দেওয়া হলো:
স্প্রিং বুট ক্লায়েন্টে ক্যাশিং ব্যবহার করে বারবার একই ডেটা পুনরুদ্ধার এড়ানো যায়।
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
@EnableCaching
অ্যানোটেশন ব্যবহার করে ক্যাশিং সক্রিয় করুন।
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableCaching
public class CacheConfig {
}
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class ApiClient {
private final RestTemplate restTemplate;
public ApiClient(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Cacheable("posts")
public String fetchPost(int postId) {
String url = "https://jsonplaceholder.typicode.com/posts/" + postId;
return restTemplate.getForObject(url, String.class);
}
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ApiController {
private final ApiClient apiClient;
public ApiController(ApiClient apiClient) {
this.apiClient = apiClient;
}
@GetMapping("/posts/{id}")
public String getPost(@PathVariable int id) {
return apiClient.fetchPost(id);
}
}
INFO - Cache hit for key: posts::1
@Async
ব্যবহার করে asynchronous কাজ করা সম্ভব।<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
@EnableAsync
ব্যবহার করে asynchronous প্রসেসিং সক্রিয় করুন।
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync
public class AsyncConfig {
}
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.concurrent.CompletableFuture;
@Service
public class AsyncApiClient {
private final RestTemplate restTemplate;
public AsyncApiClient(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@Async
public CompletableFuture<String> fetchData(String url) {
String response = restTemplate.getForObject(url, String.class);
return CompletableFuture.completedFuture(response);
}
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.CompletableFuture;
@RestController
public class AsyncController {
private final AsyncApiClient asyncApiClient;
public AsyncController(AsyncApiClient asyncApiClient) {
this.asyncApiClient = asyncApiClient;
}
@GetMapping("/async-fetch")
public CompletableFuture<String> fetchAsync() {
String url = "https://jsonplaceholder.typicode.com/posts/1";
return asyncApiClient.fetchData(url);
}
}
RestTemplate
বা WebClient
-এ Connection Pooling ব্যবহার করা হলে একই সার্ভারে একাধিক রিকোয়েস্ট দ্রুত পাঠানো সম্ভব।
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate() {
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(100);
connectionManager.setDefaultMaxPerRoute(20);
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
return new RestTemplate(requestFactory);
}
}
ডিফল্টভাবে, স্প্রিং Jackson
ব্যবহার করে JSON সিরিয়ালাইজেশন করে। পারফরম্যান্স উন্নত করার জন্য কাস্টমাইজেশন করুন।
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class JacksonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
return objectMapper;
}
}
স্প্রিং অ্যাকচুয়েটর ব্যবহার করে অ্যাপ্লিকেশনের মেট্রিক্স মনিটরিং করুন।
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
management.endpoints.web.exposure.include=*
Actuator Endpoint:http://localhost:8080/actuator/metrics
এই পদ্ধতিগুলি একত্রে ব্যবহার করলে স্প্রিং বুট ক্লায়েন্টে উল্লেখযোগ্য পারফরম্যান্স উন্নতি করা সম্ভব।
Read more