不知道怎么优化接口性能,看完这篇文章就够了
工作中经常涉及到优化Java接口性能,这篇文章总结一下优化接口性能涉及哪些方面?包括代码优化、架构优化、数据库优化、缓存策略、网络优化等。以下是详细的优化方案:
1. 代码优化
1.1 批量调用
- 单个for循环查询数据库,可以改成批量查询。
- 单个for循环插入数据库,可以改成批量插入。
- 单个for调用第三方rpc接口,可以让下游提供批量调用接口。
1.2 使用乐观锁
在并发环境中,竞争不激烈的情况下,可以考虑使用乐观锁代替悲观锁,减少CPU时间片的切换。常见的乐观锁有CAS,常见的悲观锁有Synchronized、ReentrantLock等。
1.3 避免大事务
新人程序员经常滥用事务注解@Transactional
,从而产生大事务,增加接口耗时。开发中,注意在在必要的地方加事务,缩小事务范围。
2. 缓存策略
2.1 本地缓存
使用本地缓存(如Guava Cache
或Caffeine
)来缓存热点数据,减少数据库或外部系统的访问次数。
// 使用Guava Cache
Cache<String, String> cache = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterWrite(10, TimeUnit.MINUTES)
.build();
String value = cache.getIfPresent(key);
if (value == null) {
value = database.getValue(key);
cache.put(key, value);
}
2.2 分布式缓存
使用分布式缓存(如Redis
或Memcached
)来缓存数据,适用于集群环境。
// 使用Redis
Jedis jedis = new Jedis("localhost");
String value = jedis.get(key);
if (value == null) {
value = database.getValue(key);
jedis.set(key, value);
}
秒杀环境中,为了提升秒杀扣减库存性能,可以把库存加载到Redis中,在Redis中扣减库存,最后再落库。
3. 数据库优化
3.1 索引优化
为查询频繁的列添加索引,但要避免过多索引,以免影响插入和更新性能。
3.2 SQL查询优化
- 避免复杂查询:尽量减少查询中的
JOIN
操作。 - 使用分页查询:对于返回大量数据的查询,使用分页技术,同时避免深分页问题。
3.3 数据库连接池
使用数据库连接池(如HikariCP
),并根据并发需求调整连接池大小。
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/db");
config.setUsername("user");
config.setPassword("password");
config.setMaximumPoolSize(10);
HikariDataSource dataSource = new HikariDataSource(config);
4. 网络优化
4.1 减少网络请求
尽量减少网络请求次数,可以通过批量请求、合并请求等方式减少网络开销。
4.2 CDN加速
使用内容分发网络(CDN)加速静态资源的加载。
5. 异步处理
5.1 使用异步编程模型
可以使用 Spring 框架提供的@Async
注解来实现异步调用,减少响应时间。
首先,需要启用异步支持。在配置类上添加@EnableAsync
注解。
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
@Configuration
@EnableAsync
public class AsyncConfig {
}
在服务类中定义异步方法,并使用@Async
注解。
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;
@Service
public class AsyncService {
@Autowired
private OrderService orderService;
@Async
public void cancelOrder(Long orderId) {
this.orderService.cancelOrder(orderId);
}
}
5.2 引入消息队列
通过 Kafka 实现生产者和消费者的解耦,提高系统的可扩展性。
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.beans.factory.annotation.Autowired;
@RestController
public class AsyncController {
@Autowired
private final KafkaTemplate<String, String> kafkaTemplate;
@PostMapping("/submit")
public String submitData(@RequestBody String data) {
// 将数据发送到 Kafka 主题,实现异步处理
kafkaTemplate.send("myTopic", data);
return "Data submitted successfully!";
}
}
6. 并发处理
6.1 引入线程池
使用线程池实现并发处理,提高系统吞吐量。
- 创建一个配置类,配置线程池:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
@Configuration
public class AsyncConfig {
@Bean(name = "taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("Async-");
executor.initialize();
return executor;
}
}
- 在服务类中使用线程池
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
@RestController
public class AsyncController {
@Autowired
private Executor taskExecutor;
@Autowired
private OrderService orderService;
@GetMapping("/async")
public DeferredResult<String> cancelOrder(Long orderId) {
taskExecutor.execute(() -> {
try {
orderService.cancelOrder(orderId);
} catch (Exception e) {
}
});
return "success";
}
}
转载自:https://juejin.cn/post/7381375087205908491