zoukankan      html  css  js  c++  java
  • 优化TTFB 至500ms内

    继续上一篇《优化vue+springboot项目页面响应时间:waiting(TTFB) 及content Download》 优化TTFB 至500ms内

    目前TTFB 接近1秒。再想优化,需要用到缓存技术,memcached或redis。

    暂选择memcached,将查询数据写进内存,从内存中读取。

    XMemcachedConfig.java

     1 package com.ruoyi.framework.config;
     2 
     3 import com.ruoyi.framework.config.properties.XMemcachedProperties;
     4 import net.rubyeye.xmemcached.MemcachedClient;
     5 import net.rubyeye.xmemcached.MemcachedClientBuilder;
     6 import net.rubyeye.xmemcached.XMemcachedClientBuilder;
     7 import net.rubyeye.xmemcached.command.BinaryCommandFactory;
     8 import net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator;
     9 import org.springframework.beans.factory.annotation.Autowired;
    10 import org.springframework.context.annotation.Bean;
    11 import org.springframework.context.annotation.Configuration;
    12 
    13 @Configuration
    14 public class XMemcachedConfig {
    15     @Autowired
    16     private XMemcachedProperties xMemcachedProperties;
    17 
    18     // 构建builder
    19     @Bean
    20     public MemcachedClientBuilder getXMemcachedBuilder() throws Exception{
    21         MemcachedClientBuilder memcachedClientBuilder = null;
    22         try{
    23 
    24            if ( !xMemcachedProperties.isOpenCache()) {
    25                return null;
    26            }
    27             String servers = xMemcachedProperties.getServers();
    28             memcachedClientBuilder = new XMemcachedClientBuilder(servers);
    29             // 开启/关闭failure模式
    30             memcachedClientBuilder.setFailureMode(xMemcachedProperties.isFailureMode());
    31             memcachedClientBuilder.setSanitizeKeys(xMemcachedProperties.isSanitizeKeys());
    32             memcachedClientBuilder.setConnectionPoolSize(xMemcachedProperties.getPoolSize());
    33             memcachedClientBuilder.setCommandFactory(new BinaryCommandFactory());
    34             memcachedClientBuilder.setOpTimeout(xMemcachedProperties.getOperationTimeout());
    35             memcachedClientBuilder.setSessionLocator(new KetamaMemcachedSessionLocator());
    36 
    37             return memcachedClientBuilder;
    38         }catch(Exception e){
    39             e.printStackTrace();
    40         }
    41         return null;
    42     }
    43 
    44     // client
    45     @Bean
    46     public MemcachedClient getXMemcachedClient(MemcachedClientBuilder memcachedClientBuilder) throws  Exception{
    47         MemcachedClient memcachedClient = null;
    48         try{
    49             memcachedClient = memcachedClientBuilder.build();
    50             return memcachedClient;
    51         }catch(Exception e){
    52             e.printStackTrace();
    53         }
    54         return null;
    55     }
    56 }
    View Code

    XMemcachedProperties.java

     1 package com.ruoyi.framework.config.properties;
     2 
     3 import org.springframework.boot.context.properties.ConfigurationProperties;
     4 import org.springframework.stereotype.Component;
     5 
     6 @Component
     7 @ConfigurationProperties(prefix = "memcached")
     8 public class XMemcachedProperties {
     9 
    10     private String servers;
    11     private int poolSize;
    12     private boolean isSanitizeKeys;
    13     private boolean isOpenCache;
    14     private boolean isFailureMode;
    15     private long operationTimeout;
    16 
    17     public String getServers() {
    18         return servers;
    19     }
    20 
    21     public void setServers(String servers) {
    22         this.servers = servers;
    23     }
    24 
    25     public int getPoolSize() {
    26         return poolSize;
    27     }
    28 
    29     public void setPoolSize(int poolSize) {
    30         this.poolSize = poolSize;
    31     }
    32 
    33     public boolean isSanitizeKeys() {
    34         return isSanitizeKeys;
    35     }
    36 
    37     public void setSanitizeKeys(boolean isSanitizeKeys) {
    38         this.isSanitizeKeys = isSanitizeKeys;
    39     }
    40 
    41     public boolean isOpenCache() {
    42         return isOpenCache;
    43     }
    44 
    45     public void setIsOpenCache(boolean isOpenCache) {
    46         this.isOpenCache = isOpenCache;
    47     }
    48 
    49     public boolean isFailureMode() {
    50         return isFailureMode;
    51     }
    52 
    53     public void setIsFailureMode(boolean isFailureMode) {
    54         this.isFailureMode = isFailureMode;
    55     }
    56 
    57     public long getOperationTimeout() {
    58         return operationTimeout;
    59     }
    60 
    61     public void setOperationTimeout(long operationTimeout) {
    62         this.operationTimeout = operationTimeout;
    63     }
    64 }
    View Code

    XMemcachedCache.java

      1 package com.ruoyi.common.core.xmemcached;
      2 
      3 import net.rubyeye.xmemcached.Counter;
      4 import net.rubyeye.xmemcached.MemcachedClient;
      5 import net.rubyeye.xmemcached.exception.MemcachedException;
      6 import org.springframework.beans.factory.annotation.Autowired;
      7 import org.springframework.stereotype.Component;
      8 
      9 import java.io.IOException;
     10 import java.util.concurrent.TimeoutException;
     11 
     12 /**
     13  * @author x8023z
     14  */
     15 @Component
     16 public class XMemcachedCache {
     17 
     18     @Autowired
     19     private MemcachedClient memcachedClient;
     20     private static boolean isStatus;
     21 
     22     @Override
     23     protected void finalize()
     24     {
     25         if (isStatus)
     26         {
     27             try {
     28                 memcachedClient.shutdown();
     29             } catch (IOException e) {
     30                 e.printStackTrace();
     31             }
     32         }
     33     }
     34     /**
     35      * 永久缓存基本的对象,Integer、String、实体类等
     36      *
     37      * @param key 缓存的键值
     38      * @param value 缓存的值
     39      */
     40     public <T> void setCacheObject(final String key, final T value) throws InterruptedException, TimeoutException, MemcachedException {
     41         if (memcachedClient != null) {
     42            isStatus = memcachedClient.set(key,0, value);
     43        }
     44     }
     45 
     46     /**
     47      * 缓存基本的对象,Integer、String、实体类等
     48      *
     49      * @param key 缓存的键值
     50      * @param value 缓存的值
     51      * @param timeout(单位毫秒),设置过期时间,如果expiredTime还未到期,timeout到期,则该memcached过期
     52      */
     53     public <T> void setCacheObject(final String key,  final T value, final long timeout) throws InterruptedException, TimeoutException, MemcachedException {
     54         if (memcachedClient != null) {
     55             isStatus = memcachedClient.add(key, 0, value,timeout);
     56         }
     57     }
     58 
     59     /**
     60      * 添加缓存基本的对象,Integer、String、实体类等
     61      *
     62      * @param key 缓存的键值
     63      * @param expiredTime 时间 (单位秒),超过这个时间,memcached将这个数据替换出去,0表示永久存储(默认是一个月)
     64      * @param value 缓存的值
     65      * @param timeout(单位毫秒),设置过期时间,如果expiredTime还未到期,timeout到期,则该memcached过期
     66      */
     67     public <T> void setCacheObject(final String key, final Integer expiredTime, final T value, final long timeout) throws InterruptedException, TimeoutException, MemcachedException {
     68         if (memcachedClient != null ) {
     69             isStatus = memcachedClient.add(key, expiredTime, value,timeout);
     70         }
     71     }
     72 
     73 
     74     /**
     75      * 替换缓存基本的对象,Integer、String、实体类等,注意类型是Object(统计切勿使用replace)
     76      *
     77      * @param key 缓存的键值
     78      * @param expiredTime 时间 (单位秒),超过这个时间,memcached将这个数据替换出去,0表示永久存储(默认是一个月)
     79      * @param value 缓存的值
     80      */
     81     public <T> void replaceCacheObject(final String key,  final Integer expiredTime, final T value) throws InterruptedException, TimeoutException, MemcachedException {
     82         if (memcachedClient != null) {
     83             isStatus = memcachedClient.replace(key, expiredTime, value);
     84         }
     85     }
     86 
     87     /**
     88      * 替换缓存基本的对象,Integer、String、实体类等
     89      *
     90      * @param key 缓存的键值
     91      * @param expiredTime 时间 (单位秒),超过这个时间,memcached将这个数据替换出去,0表示永久存储(默认是一个月)
     92      * @param value 缓存的值
     93      * @param timeout(单位毫秒),设置过期时间,如果expiredTime还未到期,timeout到期,则该memcached过期
     94      */
     95     public <T> void replaceCacheObject(final String key, final Integer expiredTime, final T value, final long timeout) throws InterruptedException, TimeoutException, MemcachedException {
     96         if (memcachedClient != null) {
     97             isStatus = memcachedClient.replace(key, expiredTime, value,timeout);
     98         }
     99     }
    100 
    101     /**
    102      * 永久替换缓存基本的对象,Integer、String、实体类等
    103      *
    104      * @param key 缓存的键值
    105      * @param value 缓存的值
    106      */
    107     public <T> void replaceCacheObject(final String key, final T value) throws InterruptedException, TimeoutException, MemcachedException {
    108         if (memcachedClient != null) {
    109             isStatus = memcachedClient.replace(key,0, value);
    110         }
    111     }
    112 
    113     /**
    114      * 获得缓存的基本对象。
    115      *
    116      * @param key 缓存键值
    117      * @return 缓存键值对应的数据
    118      */
    119     public <T> T getCacheObject(final String key) throws InterruptedException, TimeoutException, MemcachedException {
    120         if (memcachedClient != null) {
    121             return  memcachedClient.get(key);
    122         } else {
    123             return null;
    124         }
    125     }
    126 
    127     /**
    128      * 删除缓存的基本对象。
    129      *
    130      * @param key 缓存键值
    131      */
    132     public <T> void deleteCacheObject(final String key) throws InterruptedException, TimeoutException, MemcachedException {
    133         if (memcachedClient != null) {
    134             isStatus = memcachedClient.delete(key);
    135         }
    136     }
    137 
    138 
    139     public <T> long getStats(final String key) throws InterruptedException, MemcachedException, TimeoutException {
    140         long reCount = -1;
    141         Counter counter = null;
    142         //第二个参数是计数器的初始值
    143         if (memcachedClient != null) {
    144             counter = memcachedClient.getCounter(key,-1);
    145         }
    146         reCount = counter.get();
    147         //使用count时实质是在创建一个key,因此需要将这个key清除掉
    148         if(reCount == -1){
    149             deleteCacheObject(key);
    150         }
    151         return  reCount;
    152     }
    153 
    154 
    155     /**
    156      * 计数器累加extentOfIncrement
    157      * @param key 键
    158      * @param extentOfIncrement 递增的幅度大小
    159      * @param original key不存在的情况下的初始值
    160      * @return 计数
    161      */
    162     public <T> long addStats(String key, long extentOfIncrement, long original) throws InterruptedException, MemcachedException, TimeoutException {
    163         long reCount = -1;
    164         Counter counter = null;
    165         if (memcachedClient != null) {
    166            counter = memcachedClient.getCounter(key, original);
    167         }
    168         counter.set(extentOfIncrement+original);
    169         reCount = counter.incrementAndGet();
    170         return  reCount;
    171     }
    172 
    173     public <T> boolean getStatus()
    174     {
    175         return isStatus;
    176     }
    177 
    178 
    179 
    180 }
    View Code

    application.yml

    # memcached配置
    memcached:
      servers: 127.0.0.1:11211
      poolSize: 10
      #是否启用url encode 机制
      sanitizeKeys: false
      # true为启动缓存 false为标准实现
      isOpenCache: true
      #是否开启失败模式,默认为false
      isFailureMode: false
      #接口操作的默认超时时间,可以被接口覆盖
      operationTimeout: 3000

    修改优化之处

     1     @Autowired
     2     private XMemcachedCache memcachedcache;
     3 
     4     /**
     5      * 项目启动时,初始化参数到缓存,定时任务,每隔一分钟刷新缓存
     6      */
     7     @PostConstruct
     8     public void init() throws InterruptedException, TimeoutException, MemcachedException {
     9         loadingSysStreetCache();
    10     }
    11 
    12     /**
    13      * 设置cache key
    14      *
    15      * @param sysStreetKey 参数键
    16      * @return 缓存键key
    17      */
    18     private String getSysStreetKey(String sysStreetKey)
    19     {
    20         return Constants.SYS_STREET_KEY + sysStreetKey;
    21     }
    22 
    23     /**
    24      * 加载所有省市区镇级缓存数据
    25      */
    26 
    27 
    28     public List<TreeNodeDict> loadingSysStreetCache() throws InterruptedException, TimeoutException, MemcachedException {
    29         List<SysStreet> list = streetService.selectStreetListView(new SysStreet());
    30         TreeDataConvertUtils tree = new TreeDataConvertUtils();
    31         List<TreeNodeDict> collect = list.stream()
    32                 .map(a-> new TreeNodeDict(a.getCode(), a.getName(), a.getProvinceCode()))
    33                 .collect(Collectors.toList());
    34 
    35         // 后台返回非树结构的list,前端处理慢
    36         // return AjaxResult.success(list);
    37         // 后台返回树结构list,前端处理快
    38         // return AjaxResult.success(tree.convertToTreeUseMap(collect,"1"));
    39 
    40         List<TreeNodeDict>  treeNodes =tree.convertToTreeUseMap(collect,"1");
    41         // 序列化
    42         if (memcachedcache != null) {
    43           memcachedcache.setCacheObject(getSysStreetKey(""), JSON.toJSONString(treeNodes));
    44         }
    45         return treeNodes;
    46     }
    View Code
    // 注意使用之时,返回前端需要反序列化
    public AjaxResult listview(SysStreet street) throws InterruptedException, TimeoutException, MemcachedException {
    List<TreeNodeDict> listTreeNodeDict = null;
    if (memcachedcache != null && memcachedcache.getStatus() ) {
    // 反序列化
    listTreeNodeDict = JSON.parseArray(memcachedcache.getCacheObject(getSysStreetKey("")), TreeNodeDict.class);
    }
    if (listTreeNodeDict == null || listTreeNodeDict.size() ==0 )
    {
    listTreeNodeDict = loadingSysStreetCache();
    }

    return AjaxResult.success(listTreeNodeDict);
    }

    优化结果:

  • 相关阅读:
    Linux编程 22 shell编程(输出和输入重定向,管道,数学运算命令,退出脚本状态码)
    mysql 开发进阶篇系列 46 物理备份与恢复( xtrabackup的 选项说明,增加备份用户,完全备份案例)
    mysql 开发进阶篇系列 45 物理备份与恢复(xtrabackup 安装,用户权限,配置)
    mysql 开发进阶篇系列 44 物理备份与恢复( 热备份xtrabackup 工具介绍)
    Linux编程 21 shell编程(环境变量,用户变量,命令替换)
    Linux编程 20 shell编程(shell脚本创建,echo显示信息)
    mysql 开发进阶篇系列 43 逻辑备份与恢复(mysqldump 的基于时间和位置的不完全恢复)
    Linux编程 19 编辑器(vim 用法)
    (网页)angularjs中的interval定时执行功能(转)
    (网页)在SQL Server中为什么不建议使用Not In子查询(转)
  • 原文地址:https://www.cnblogs.com/zjp8023/p/15763908.html
Copyright © 2011-2022 走看看