likes
comments
collection
share

不知道怎么优化接口性能,看完这篇文章就够了

作者站长头像
站长
· 阅读数 47

工作中经常涉及到优化Java接口性能,这篇文章总结一下优化接口性能涉及哪些方面?包括代码优化、架构优化、数据库优化、缓存策略、网络优化等。以下是详细的优化方案:

1. 代码优化

1.1 批量调用

  • 单个for循环查询数据库,可以改成批量查询。
  • 单个for循环插入数据库,可以改成批量插入。
  • 单个for调用第三方rpc接口,可以让下游提供批量调用接口。

1.2 使用乐观锁

在并发环境中,竞争不激烈的情况下,可以考虑使用乐观锁代替悲观锁,减少CPU时间片的切换。常见的乐观锁有CAS,常见的悲观锁有Synchronized、ReentrantLock等。

1.3 避免大事务

新人程序员经常滥用事务注解@Transactional,从而产生大事务,增加接口耗时。开发中,注意在在必要的地方加事务,缩小事务范围。

2. 缓存策略

2.1 本地缓存

使用本地缓存(如Guava CacheCaffeine)来缓存热点数据,减少数据库或外部系统的访问次数。

// 使用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 分布式缓存

使用分布式缓存(如RedisMemcached)来缓存数据,适用于集群环境。

// 使用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 引入线程池

使用线程池实现并发处理,提高系统吞吐量。

  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;
    }
}
  1. 在服务类中使用线程池
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
评论
请登录