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中让普通用户拥有超级用户的权限
    python 正则表达式应用——缩写词扩充
    解决单链表中的环问题
    python数学函数
    train,dev,test数据集作用
    朴素贝叶斯法(二)——基本方法
    生成模型与判别模型
    ImportError: cannot import name wordnet
  • 原文地址:https://www.cnblogs.com/zjp8023/p/15763908.html
Copyright © 2011-2022 走看看