Yun Qi Hao: https://yqh.aliyun.com
The first-hand cloud information, the selected cloud enterprise case base of different industries, and the best practices extracted from many successful cases help you to make cloud decision!
background
Occasionally, there are some slow requests in the production environment, resulting in system performance degradation and throughput degradation. Here are some optimization suggestions.
programme
1. Under to replace tomcat
Most e-commerce websites are short requests, and the response time is generally 100ms. At this time, you can replace the web container from tomcat to underow. The following steps are introduced: 1. Add pom configuration
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> <exclusions> <exclusion> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-tomcat</artifactid> </exclusion> </exclusions> </dependency> <dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-undertow</artifactid> </dependency>
2. Add related configuration
server: undertow: direct-buffers: true io-threads: 4 worker-threads: 160
Restart. You can see that the container has been switched to "below" in the console
2, cache
Put some hot data or static data into the local cache or redis, and update the cache data regularly if necessary
3, asynchronous
In the code process, many of our codes do not need to wait for the return result, that is to say, part of the code can be executed in parallel. At this time, Async can be used. The simplest solution is to use @ Async annotation provided by springboot, which can also be realized through thread pool. The following is a brief introduction of asynchronous steps. 1. pom dependency general springboot introduces web dependency
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-web</artifactid> </dependency>
2. Add @ EnableAsync annotation to startup class
@EnableAsync @SpringBootApplication public class AppApplication { public static void main(String[] args) { SpringApplication.run(AppApplication.class, args); } }
3. Add @ Async annotation in the specified method if necessary. If you need to wait for the return value, the demo is as follows
@Async public Future<string> doReturn(int i){ try { // This method takes 500 milliseconds to call Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } / Message aggregation return new AsyncResult<>("Asynchronous call"); }
4. If there is thread variable or mdc in logback, you can increase the delivery
import org.slf4j.MDC; import org.springframework.context.annotation.Configuration; import org.springframework.core.task.TaskDecorator; import org.springframework.scheduling.annotation.AsyncConfigurerSupport; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.Map; import java.util.concurrent.Executor; /** * @Description: */ @EnableAsync @Configuration public class AsyncConfig extends AsyncConfigurerSupport { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setTaskDecorator(new MdcTaskDecorator()); executor.initialize(); return executor; } } class MdcTaskDecorator implements TaskDecorator { @Override public Runnable decorate(Runnable runnable) { Map<string, string> contextMap = MDC.getCopyOfContextMap(); return () -> { try { MDC.setContextMap(contextMap); runnable.run(); } finally { MDC.clear(); } }; } }
5. Sometimes asynchrony needs to increase blocking
import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; import java.util.concurrent.ThreadPoolExecutor; @Configuration @Slf4j public class TaskExecutorConfig { @Bean("localDbThreadPoolTaskExecutor") public Executor threadPoolTaskExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(200); taskExecutor.setQueueCapacity(200); taskExecutor.setKeepAliveSeconds(100); taskExecutor.setThreadNamePrefix("LocalDbTaskThreadPool"); taskExecutor.setRejectedExecutionHandler((Runnable r, ThreadPoolExecutor executor) -> { if (!executor.isShutdown()) { try { Thread.sleep(300); executor.getQueue().put(r); } catch (InterruptedException e) { log.error(e.toString(), e); Thread.currentThread().interrupt(); } } } ); taskExecutor.initialize(); return taskExecutor; } }
4, Business split
You can split the time-consuming or different businesses to provide the throughput of a single node
5. Integrated message queuing
There are many scenarios where the requirements for real-time data are not so strong, or messages can be sent to kafka for business fault-tolerant processing, and then consumption is delayed. For example, you can query the specified user to send push messages according to the criteria. Here, you can send push messages on time, by day, by month, and so on
Yun Qi Hao: https://yqh.aliyun.com
The first-hand cloud information, the selected cloud enterprise case base of different industries, and the best practices extracted from many successful cases help you to make cloud decision!
Original release time: February 19, 2020
By Lipeng Heke
This article comes from:“ Internet architect official account ”, you can pay attention to“ Internet architect"