خلاصه مطلب
Spring Boot رایجترین فریمورک برای ایجاد APIهای REST در جاوا است. این فریمورک تمامی تنظیمات و کدهای پیشفرض را مدیریت میکند و ما تنها باید منطق اصلی را…
تصویر مرتبط؛ کاور اختصاصی جاواپرو، نه تصویر آموزشیِ منبع اصلی
7 تکنیک پیشرفته برای بهبود عملکرد API در Spring Boot
Spring Boot رایجترین فریمورک برای ایجاد APIهای REST در جاوا است. این فریمورک تمامی تنظیمات و کدهای پیشفرض را مدیریت میکند و ما تنها باید منطق اصلی را پیادهسازی کنیم.
با بزرگتر شدن API و استفاده زیاد مشتریان، ممکن است عملکرد آن کاهش یابد.
در این مقاله به بررسی چند تکنیک میپردازیم که میتواند عملکرد API در برنامههای Spring Boot را بهبود بخشد.
استفاده کارآمد از @Async و @CompletableFuture
Spring Boot محدودیتی در تعداد درخواستهای همزمان دارد. اما اگر محاسبات سنگینی وجود داشته باشد که میتوان آنها را در یک نخ جداگانه اجرا کرد، این کار میتواند به بهبود عملکرد منجر شود.
برخی وظایف، مانند لاگگذاری، میتوانند به صورت غیرهمزمان انجام شوند تا تأخیر API کاهش یابد.
مثال استفاده از @Async با CompletableFuture
ابتدا باید Async را فعال کنیم:
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync // Magic switch!
public class AsyncConfig {
// You can also configure the thread pool executor here
// for more control, but Spring provides a default one.
}ایجاد یک سرویس
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@Service
public class SlowService {
@Async // Tells Spring to run this in a separate thread
public CompletableFuture<String> performSlowTask(String input) {
System.out.println("Starting slow task for: " + input + " on thread: " + Thread.currentThread().getName());
try {
// Simulate a long-running operation (e.g., external API call)
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return CompletableFuture.failedFuture(e);
}
String result = "Processed: " + input;
System.out.println("Finished slow task for: " + input);
return CompletableFuture.completedFuture(result); // Return the result wrapped in a CompletableFuture
}
}سپس میتوانیم سرویس را به این صورت فراخوانی کنیم:
CompletableFuture<String> futureresult = slowService.performSlowTask(data);برنامهنویسی واکنشگرا با استفاده از Spring WebFlux
Spring WebFlux یک فریمورک غیرمسدودکننده و واکنشگرا است. این فریمورک از مدل event-loop استفاده میکند که تعداد کمی نخ ثابت دارد تا ارتباطات همزمان بسیاری را بهطور کارآمد مدیریت کند.
@GetMapping("/reactive-process")
public Mono<String> processReactively(@RequestParam String data) {
System.out.println("Received reactive request for: " + data);
// Simulate a non-blocking delay (like a reactive API call)
return Mono.delay(Duration.ofSeconds(2))
.map(d -> "Reactively processed: " + data)
.doOnNext(result -> System.out.println("Finished reactive task for: " + data));
}تنظیمات پیشرفته پایگاه داده
پایگاههای داده معمولاً بزرگترین عامل محدودکننده در بهبود عملکرد API هستند.
حتی اگر شاخصها تنظیم شده باشند، استراتژیها و پرسوجوهای ناکارآمد میتوانند منجر به عملکرد ضعیف شوند.
چه تکنیکهایی میتوانند در این زمینه کمک کنند؟
- استفاده از یک پرسوجو واحد، میتوانیم از @EntityGraph یا join FETCH در JPQL برای بارگذاری موجودیتهای مرتبط به صورت eager استفاده کنیم. همچنین میتوانیم از DTO projections برای دریافت تنها فیلدهای موردنیاز استفاده کنیم.
- استفاده از Batching برای وارد کردن و بهروزرسانیهای انبوه. این کار با ترکیب چندین عبارت SQL در یک زمان، از تعداد سفرهای شبکه میکاهد.
- در صورت سنگین بودن عملیات خواندن، از Read Replicas استفاده کنیم.
استفاده از استراتژیهای کش پیشرفته(Using Advanced Caching Strategies)
همه ما میدانیم که کش میتواند عملکرد را با بازگرداندن نتایج به جای درخواست دادههای مشابه از پایگاه داده یا تماسهای شبکهای، بهبود بخشد.
- استفاده از ارائهدهندگان کش خارجی مانند Redis یا Hazelcast. این مهم است در سیستمهای توزیعشده و به راحتی مقیاسپذیر است.
- پیکربندی کنترلهای کش مانند TTL، سیاست تخلیه و کش شرطی.
- میتوانیم از کش گرمکن برای زمانی که به طور مکرر به دادهها دسترسی داریم، استفاده کنیم.
بهینهسازی سریالسازی دادهها(Optimizing the Data Serialization)
سریالسازی یا دسیریالسازی میتواند زمان و حافظه زیادی برای اشیاء پیچیده بزرگ مصرف کند.
- میتوانیم از ویژگیهای ObjectMapper مانند Views برای ارسال تنها فیلدهای موردنیاز استفاده کنیم.
- میتوانیم از فرمتهای جایگزین با اندازههای بار بسیار کوچکتر، مانند Protobuf، استفاده کنیم.
برای استفاده از Protobuf، مراحل زیر را باید طی کنیم:
- ایجاد یک فایل .proto
- تولید کد جاوا با استفاده از این فایلها.
- پیکربندی Spring Boot برای استفاده از مبدلهای پیام Protobuf.
مثال فایل product.proto
syntax = "proto3";
package com.example.proto;
option java_package = "com.example.myapp.dto.proto";
option java_outer_classname = "ProductProtos";
message Product {
int64 id = 1;
string name = 2;
double price = 3;
}پیکربندی فشردهسازی درخواست و پاسخ
پاسخهای API میتوانند بزرگ باشند، بهویژه اگر از JSON استفاده میکنیم. این میتواند باعث کاهش تأخیر API شود، زیرا هرچه اندازه بسته بزرگتر باشد، زمان بیشتری برای انتشار آن در شبکه نیاز است.
میتوانیم Spring Boot را برای فشردهسازی خودکار پاسخهای HTTP با استفاده از GZip یا سایر فناوریهای فشردهسازی پیکربندی کنیم.
نمونهای از application.properties برای فشردهسازی پاسخها
# Enable response compression
server.compression.enabled=true
# Specify the MIME types that should be compressed
server.compression.mime-types=application/json,application/xml,text/html,text/xml,text/plain,application/javascript,text/css
# Minimum response size (bytes) to trigger compression. Don't compress tiny responses.
server.compression.min-response-size=2048 # Compress only if response is > 2KB
# You can also specify which user agents to exclude (if some have issues)
# server.compression.excluded-user-agents=some-buggy-client
# Brotli support (if available on the server classpath/environment - requires specific setup)
# server.compression.brotli.enabled=trueتنظیمات JVM
بسیاری از تنظیمات JVM میتوانند بر عملکرد و پایداری API تأثیر بگذارند.
- میتوانیم اندازههای اولیه و حداکثر heap را بر اساس نیازهای حافظه برنامه در زمان بارگذاری تنظیم کنیم. این کار ممکن است به کاهش هزینههای GC و کاهش سربار JVM برای تغییر اندازه heap کمک کند.
- در حال حاضر G1GC به عنوان جمعآور زباله پیشفرض استفاده میشود. میتوانیم آن را بر اساس نیاز تغییر دهیم.
نمونهای از تنظیمات JVM
# Start with 1GB initial heap, 2GB max heap, using G1GC
java -Xms1g -Xmx2g -XX:+UseG1GC -jar your-springboot-app.jar
# Example: Potentially using ZGC (requires compatible JDK)
# java -Xms2g -Xmx2g -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -jar your-springboot-app.jarنکات پایانی
در این مقاله تکنیکهای پیشرفتهای برای بهبود عملکرد API پوشش داده شد. اما نکات مهمی نیز باید در نظر گرفته شوند:
- ابتدا باید برنامه را پروفایل کنیم تا مشکلات واقعی را شناسایی کنیم. میتوانیم از ابزارهایی مانند VisualVM، JProfiler و غیره استفاده کنیم.
- تکنیکها را بر اساس پروفایل انتخاب کنیم. از بهینهسازی بیش از حد خودداری کنیم، زیرا ممکن است مشکلات بیشتری ایجاد کند.
- باید تریدآفها بین CPU، حافظه، پهنای باند شبکه و غیره را در نظر بگیریم.
لیست دوره های آکادمی جاواپرو
- دوره پرتاب | آموزش پیش نیازهای قبل از شروع برنامه نویسی
- دوره مقدماتی زبان برنامه نویسی جاوا
- دوره جامع شاهکار پیشرفته جاوا
- دوره جامع طلایی Spring Core
- دوره آموزش فریمورک Spring Boot
- دوره پروژه محور Spring Boot - سیستم دانشگاه
- دوره جامع دژبان Spring security
- دوره جامع نخبگان معماری میکروسرویس با Java و Spring Boot

