通过多线程编排优化小说内容页性能,提高系统吞吐量

原创
2021/01/25 16:50
阅读数 6.3K
AI总结

前言

小说内容页作为小说精品屋-plus中的核心模块页面,承载着用户90%以上的访问量,下面将详细讲解小说内容页的设计和实现,以及如何通过多线程来提高小说内容页的性能和系统吞吐量。

优化效果

优化前(业务代码单线程串行执行):

优化后(业务代码多线程并行执行):

设计与实现

  1. application.yml配置文件中新建线程池配置。
    #线程池配置
    thread:
      pool:
        #核心线程池数量
        core-pool-size: 10
        #最大线程池数量
        maximum-pool-size: 20
        #线程超时时间(秒)
        keep-alive-time: 10
        #队列大小
        queue-size: 100

     

  2. 新建线程池配置属性类。
    @Data
    @Component
    @ConfigurationProperties(prefix = "thread.pool")
    public class ThreadPoolProperties {
    
        private Integer corePoolSize;
        private Integer maximumPoolSize;
        private Long keepAliveTime;
        private Integer queueSize;
    
    
    }

     

  3. 新建线程池配置类。
    @Configuration
    public class ThreadPoolConfig {
    
        @Bean
        public ThreadPoolExecutor threadPoolExecutor(ThreadPoolProperties properties) {
            return new ThreadPoolExecutor(properties.getCorePoolSize(), properties.getMaximumPoolSize(),
                properties.getKeepAliveTime(), TimeUnit.SECONDS, new LinkedBlockingDeque<>(properties.getQueueSize()),
                new ThreadPoolExecutor.AbortPolicy());
        }
    
    }

     

  4. 业务代码实现。
    //加载小说基本信息线程
    CompletableFuture<Book> bookCompletableFuture = CompletableFuture
    	.supplyAsync(() -> {
    		//查询书籍
    		Book book = bookService.queryBookDetail(bookId);
    		log.debug("加载小说基本信息线程结束");
    		return book;
    	}, threadPoolExecutor);
    
    //加载小说章节信息线程
    CompletableFuture<BookIndex> bookIndexCompletableFuture = CompletableFuture
    	.supplyAsync(() -> {
    		//查询目录
    		BookIndex bookIndex = bookService.queryBookIndex(bookIndexId);
    		log.debug("加载小说章节信息线程结束");
    		return bookIndex;
    	}, threadPoolExecutor);
    
    //加载小说上一章节信息线程,该线程在加载小说章节信息线程执行完毕后才执行
    CompletableFuture<Long> preBookIndexIdCompletableFuture = bookIndexCompletableFuture
    	.thenApplyAsync((bookIndex) -> {
    		//查询上一章节目录ID
    		Long preBookIndexId = bookService.queryPreBookIndexId(bookId, bookIndex.getIndexNum());
    		log.debug("加载小说上一章节信息线程结束");
    		return preBookIndexId;
    	}, threadPoolExecutor);
    
    //加载小说下一章节信息线程,该线程在加载小说章节信息线程执行完毕后才执行
    CompletableFuture<Long> nextBookIndexIdCompletableFuture = bookIndexCompletableFuture
    	.thenApplyAsync((bookIndex) -> {
    		//查询下一章目录ID
    		Long nextBookIndexId = bookService.queryNextBookIndexId(bookId, bookIndex.getIndexNum());
    		log.debug("加载小说下一章节信息线程结束");
    		return nextBookIndexId;
    	}, threadPoolExecutor);
    
    //加载小说内容信息线程
    CompletableFuture<BookContent> bookContentCompletableFuture = CompletableFuture
    	.supplyAsync(() -> {
    		//查询内容
    		BookContent bookContent = bookService.queryBookContent(bookIndexId);
    		log.debug("加载小说内容信息线程结束");
    		return bookContent;
    	}, threadPoolExecutor);
    
    //判断用户是否需要购买线程,该线程在加载小说章节信息线程执行完毕后才执行
    CompletableFuture<Boolean> needBuyCompletableFuture = bookIndexCompletableFuture
    	.thenApplyAsync((bookIndex) -> {
    		//判断该目录是否收费
    		if (bookIndex.getIsVip() != null && bookIndex.getIsVip() == 1) {
    			//收费
    			UserDetails user = getUserDetails(request);
    			if (user == null) {
    				//未登录,需要购买
    				return true;
    			}
    			//判断用户是否购买过该目录
    			boolean isBuy = userService.queryIsBuyBookIndex(user.getId(), bookIndexId);
    			if (!isBuy) {
    				//没有购买过,需要购买
    				return true;
    			}
    		}
    
    		log.debug("判断用户是否需要购买线程结束");
    		return false;
    
    	}, threadPoolExecutor);

     

总结

通过小说精品屋-plus小说内容页的设计和实现,我们可以发现使用多线程优化的核心主要在于对线程池核心线程数、最大线程数、队列大小等参数的选择,这些配置参数应该根据实际环境来决定,我们可以通过压力测试工具如JMeter来辅助我们确定这些参数的最优值范围。

 

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
2
分享
AI总结
返回顶部
顶部