发表于: 2018-01-30 11:38:09

2 673


今天完成的事情

 1.任务的验收标准

 (1)首先是系统可以在500ms返回时的tps:

   经过很多次变更调试,最终确定全部请求时键500ms以内的线程数最大是22,最大循环次数1:

也尝试了微调,比如23线程:

也就不满足条件了,也尝试稍微加上一次循环,也就是22线程2次循环:

也已经不符合条件。

那么符合条件的就是22线程1s启动循环1次,它的tps视图:

因为线程数和循环数都很小,总请求就很少,所以它是一条直线。那就得出结论了,系统可以再500ms内返回时的tps是18.3。

 (2)系统宕机时候的负载:

 首先我得定义宕机,我认为测试被迫停止或者就是宕机,没有按照设置跑完就宕机了。

100线程1s启动的情况:

虽然没有宕机,但是响应时间已经非常的长了,但是这还没宕机,调到200线程:

虽然各个参数都挺惨,但是仍然没有宕机,接下来调到300线程:

嗯。。还没有,直接加到500线程:

已经卡住了,并且出现了错误,在观察过程中错误率一直在波动,是因为错误在不断的出现,可以认为此时已经宕机了。

 于是结论是:500线程1s启动的时候宕机了。

  (3)TPS稳定时的响应时长:

  那么调整线程数,达到让tps稳定:

可以看到除了画圈的部分,整体比较稳定,分别对应的是0-20s和49-59s以及1.19-1.39s,那么查看这几个区间的响应时间:

那么可以看到这写区间的响应时间,但是这个图并不是很好,因为刻度太大了,我们只能估摸着来,稳定的时候大概在1.5s左右,不过很多值是小于这个数的

 2.那么接下来就是模拟缓存穿透的情况:想想一想要怎么模拟,而且缓存穿透是什么?

  这样说吧,本来存在缓存的时候,请求会从环中取出数据,而有的时候突然跑到了数据库中去拿数据,就是缓存穿透了,缓存没能拦住这个请求。也就是说要创走啊这样一个情况:让请求又从缓存拿的,有从数据库拿的,然后对比一下情况。看看缓存穿透的时候会发生些什么。

  那么需要在代码里面更改一些,加上一个判断,来查看一波

public static int i = 0;//定义全局静态变量,来保存数据


public List<Pros> getAllPros(){
i++;
   System.out.println(i);
   List<Pros> pross;

   if (redisUtil.get("pross") != null&&i%9!=0){
pross = (List<Pros>)redisUtil.get("pross");
       System.out.println("从缓存中取到的哦");
    //   return pross;
   }else{
pross = pageDao.getAllPros();
       redisUtil.set("pross",pross);
       System.out.println("从数据库取到的哦");
     //  return pross;
   }
return pross;
}

  这样的话,只有9的倍数次访问的时候才会模拟击穿缓存。

很清晰。

然后在使用jmeter测试的时候效果并不直观,数据太过笼统,于是选择了postman来测试:

这是一次缓存穿透的响应时间。然后下面是直接使用缓存的:

然后赶上下一次的穿透:

还是比较直观的,大概20%的提升吧,而且我觉得在多线程访问的时候肯定效果更好。

附上简书链接,图都挂了:https://www.jianshu.com/p/7ef8000e1365

3.接下来开始准备提交任务

下面是官方的脑图:

任务名称:task6

成果链接:http://47.93.229.36/task6RedisDemo/

任务耗时:1.27-1.30共计四天,没有延期

任务脑图:

下面是官方的脑图:

任务总结:

a.任务进度在预期之内,都在计划之中

b.脑图对比,发现还是层次上有一些问题吧,关于知识点的梳理分类,稍有欠缺。

c.任务中碰到问题,在这里简单说一下:

   按照任务要求的顺序来说吧:节点1的说明:程序挂掉的含义很模糊,各位大佬也没说出个标准来,只能按照自己顶的标准来进行。

  节点2的说明:使用Memcached还是顺风顺水的,挺好使的,也很轻松,没什么好说的

  节点3的说明:nginx的负载均衡,这个东西在任务二的时候已经做过,更是没啥好说的了,稍微注意下验证成功的方法吧,我是通过查看nginx的日志来判断的。

  节点4的说明:节点4真的是问题比较难受,spring和redis的整合过程中真的碰到了很多很多的问题,不过都不是什么很难的东西,大家使用redis的时候注意jar包的版本就好了,完全没问题的。

  大总结一下,其实这部分任务真的耗时挺短的,大家首先搞清楚压力测试是什么,然后缓存是什么,负载均衡是什么,结合我上面说到的问题,就可以比较轻松地通关。

  4.正好借此总结一下知识点吧:

在任务六中涉及到的新的知识点也就是缓存了,毕竟压力测试这块儿是借用的工具来模拟,那接下来就说说缓存:

  提到缓存,其他的存也要说一下:

外存:

  也就是我们经常说的(CDEF盘的大小)外储存器是指除计算机内存及CPU缓存以外的储存器,此类储存器一般断电后仍然能保存数据。常见的外存储器有硬盘、软盘、光盘、U盘等,一般的软件都是安装在外存中

内存:

  内存是计算机中重要的部件之一,它是与CPU进行沟通的桥梁。计算机中所有程序的运行都是在内存中进行的,因此内存的性能对计算机的影响非常大。内存(Memory)也被称为内存储器,其作用是用于暂时存放CPU中的运算数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来,内存的运行也决定了计算机的稳定运行,此类储存器一般断电后数据就会被清空

高速缓存:

  高速缓存是用来协调CPU与主存之间存取速度的差异而设置的。一般情况下,CPU的工作速度高,但内存的工作速度相对较低,为了解决这个问题,通常使用高速缓存,高速缓存的存取速度介于CPU和主存之间。系统将一些CPU在近几个时间段经常访问的内容存入高速缓冲,当CPU需要使用数据时,先在高速缓存中找,如果找到,就不必访问内存了,找不到时,再找内存,这样就在一定程度上缓解了由于主存速度低造成的CPU“停工待料”的情况

简单讲就是,如果某些资源或者数据会被频繁的使用,而这些资源或数据存储在系统外部,比如数据库、硬盘文件等,那么每次操作这些数据的时候都从数据库或者硬盘上去获取,速度会很慢,会造成性能问题。
  一个简单的解决方法就是:把这些数据缓存到内存里面,每次操作的时候,先到内存里面找,看有没有这些数据,如果有,那么就直接使用,如果没有那么就获取它,并设置到缓存中,下一次访问的时候就可以直接从内存中获取了。从而节省大量的时间,当然,缓存是一种典型的空间换时间的方案。

  在Java中最常见的一种实现缓存的方式就是使用Map, 基本的步骤是:
     先到缓存里面查找,看看是否存在需要使用的数据
    如果没有找到,那么就创建一个满足要求的数据,然后把这个数据设置回到缓存中,以备下次使用
     如果找到了相应的数据,或者是创建了相应的数据,那就直接使用这个数据。

也就是缓冲存储,我的理解就是假存储,并不会永久存在,只是在一段时间内可以使用,并且速度比较快,用它来保存数据读取数据都比较轻松。怒过因为学习的层面比较浅,很多东西还没涉及到。

  既然知道了什么是缓存,就来了解一下使用的Memcached和redis,这两个东西吧:

Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

上面就Memcached的定义了,连它做啥字都非常的清楚,在web项目中使用的时候要借助工具类:


import com.whalin.MemCached.MemCachedClient;
import com.whalin.MemCached.SockIOPool;

public class MemcachedUtil {
/**
    * memcached客户端单例
    */
   private static MemCachedClient cachedClient = new MemCachedClient();

   /**
    * 初始化连接池
    */
   static {
//获取连接池的实例
       SockIOPool pool = SockIOPool.getInstance();

       //服务器列表及其权重
//        可以是多个服务器
       String[] servers = {"127.0.0.1:11211"};
       Integer[] weights = {3};

       //设置服务器信息
       pool.setServers(servers);
       pool.setWeights(weights);

       //设置初始连接数、最小连接数、最大连接数、最大处理时间
       pool.setInitConn(10);
       pool.setMinConn(10);
       pool.setMaxConn(1000);
       pool.setMaxIdle(1000*60*60);

       //设置连接池守护线程的睡眠时间
       pool.setMaintSleep(60);

       //设置TCP参数,连接超时
       pool.setNagle(false);
       pool.setSocketTO(60);
       pool.setSocketConnectTO(0);

       //初始化并启动连接池
       pool.initialize();

       //压缩设置,超过指定大小的都压缩
//      cachedClient.setCompressEnable(true);
//      cachedClient.setCompressThreshold(1024*1024);
   }

private MemcachedUtil(){
}

public static boolean add(String key, Object value) {
return cachedClient.add(key, value);
   }

public static boolean add(String key, Object value, Integer expire) {
return cachedClient.add(key, value, expire);
   }

public static boolean put(String key, Object value) {
return cachedClient.set(key, value);
   }

public static boolean put(String key, Object value, Integer expire) {
return cachedClient.set(key, value, expire);
   }

public static boolean replace(String key, Object value) {
return cachedClient.replace(key, value);
   }

public static boolean replace(String key, Object value, Integer expire) {
return cachedClient.replace(key, value, expire);
   }

public static Object get(String key) {
return cachedClient.get(key);
   }
}

  借助这个工具类就可以在项目中将数据加到缓存中:

@Autowired
public PageDao pageDao;

public List<Pros> getAllPros(){
System.out.println("要进入缓存了");
   List<Pros> pross ;
   if (MemcachedUtil.get("pross")!= null){
System.out.println("这说明有缓存啊");
       pross = (List<Pros>) MemcachedUtil.get("pross");
       return pross;
   }else{
System.out.println("这说明没有缓存啊");
       pross = pageDao.getAllPros();
       MemcachedUtil.put("pross",pross,600);
       return pross;
   }
}

 就像上面这样使用,加进缓存和从缓存中取出来。

嗯。。。好多东西都没有用到,我也不再这里赘述了。

  在这就是redis的使用了,其实和上面的这个东西是一样的,只不过安装的整合的时候真的是费劲,注意版本号!

  一定要全部对应好才可以使用!!!!!!!!!!!!!!!!!!!!!!

  一定要全部对应好才可以使用!!!!!!!!!!!!!!!!!!!!!!

  一定要全部对应好才可以使用!!!!!!!!!!!!!!!!!!!!!!

  最后的话提一嘴负载均衡,这个东西没啥难的吧。。虽然我当时也快被虐哭了,但是返回来一看还是挺简单的。

  好了,任务六就总结到这里吧。

5.开始搞任务七。。

  完成了节点1:

 新增了字段:

不过暂时不太清楚头像这块儿应该怎么处理。

  6.然后帮助同学解决问题的时候虽然解决了问题,但是尝试例外的方法是失败了。

是template的语句拼接出现了问题,多亏明达大佬

在template的实体类里面插入Students students的时候对应的插入语句那块儿有个拼接:

 jdbcTemplateObject.update( SQL,id,name,age);这是参数写全的情况用的

 jdbcTemplateObject.update( SQL,student.getid(),student.getname(),student.getage());

这是参数只写Student student的情况。

涨了一波知识。

今天遇到的问题

  发现自己没学习json,明天将json的相关知识补一补,之前涉及的太浅了。

今天的收获:

  今天完成了任务六,查漏补缺,发现了欠缺的知识点,这块儿除了json已经没任何遗憾了。

明天计划的事情:

  明天计划补上json的学习,然后继续深入任务7


返回列表 返回列表
评论

    分享到