发表于: 2017-10-22 23:48:35

1 748


一.今日完成

1.梳理JMeter和badboy在性能测试中的作用

(1)关于badboy,官网提供了一版教程<Badboy v2.1User Documentation>(http://www.badboy.com.au/docs/Badboy_v2.1_User_Doc.pdf),但是英文文档阅读起来相当吃力,有测试人员总结了badboy的系列资料(http://leafwf.blog.51cto.com/all/872759/page/2),从界面介绍,录制, 创建suites,tests,steps和Template,运行脚本,参数化, Variable Setter, Incrementing Variables,查看回放结果,导出脚本用于JMeter性能测试和导出脚本用于Jmeter并发测试等方面对badboy作了详细分析和demo说明.

(2)对于JMeter,推荐<零成本实现Web性能测试---基于Apache JMeter>(温紫剑编著 电子工业出版社)一书,首先介绍了基础的性能测试理论,接着详细介绍如何使用JMeter来完成各种类型的性能测试,以及如何分析性能测试的结果.

一般,创建测试计划的办法就是使用JMeter代理,即完成录制发往服务器的请求.由于JMeter不支持HTTPS协议,所以配合使用badboy作为JMeter代理的录制.

2.梳理memcached的实现原理

日本mixi的两名工程师在2008年撰写了连载文章《memcachedを知り尽くす》,虽然时间久远,但是非常适合memcached入门的人阅读(http://gihyo.jp/dev/feature/01/memcached/).其中,对memcached的内存存储机制,删除机制,分布式算法,memcached的应用和兼容程序等作了详细说明,尤其是内存存储机制和删除机制及分布式算法部分,清晰明了,毫不拖泥带水.中文翻译参见http://charlee.li/memcached-001.html

3.梳理redis相关知识

(1)常用的数据类型

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

(2)Redis 事务可以一次执行多个命令,常用事务命令包括

1)DISCARD 取消事务,放弃执行事务块内的所有命令。

2)EXEC 执行所有事务块内的命令。

3)MULTI 标记一个事务块的开始。

4)UNWATCH 取消 WATCH 命令对所有 key 的监视。

5) WATCH key [key ...] 监视一个(或多个) key ,如果在事务执行之前这个(或这些) key 被其他命令所改动,那么事务将被打断。

(3)Redis 发布订阅

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。常用命令包括:

1)PSUBSCRIBE pattern [pattern ...] 订阅一个或多个符合给定模式的频道。

2) PUBSUB subcommand [argument [argument ...]] 查看订阅与发布系统状态。

3)PUBLISH channel message 将信息发送到指定的频道。

4)PUNSUBSCRIBE [pattern [pattern ...]] 退订所有给定模式的频道。

5)SUBSCRIBE channel [channel ...] 订阅给定的一个或多个频道的信息。

6)UNSUBSCRIBE [channel [channel ...]] 指退订给定的频道。

(4)Redis 脚本

Redis 脚本使用 Lua 解释器来执行脚本。 执行脚本的常用命令为 EVAL。

1)EVAL script numkeys key [key ...] arg [arg ...] 执行 Lua 脚本。

2) EVALSHA sha1 numkeys key [key ...] arg [arg ...] 执行 Lua 脚本。

3)SCRIPT EXISTS script [script ...] 查看指定的脚本是否已经被保存在缓存当中。

4)SCRIPT FLUSH 从脚本缓存中移除所有脚本。

5)SCRIPT KILL 杀死当前正在运行的 Lua 脚本。

6) SCRIPT LOAD script 将脚本 script 添加到脚本缓存中,但并不立即执行这个脚本。

(5)Jedis连接池的使用

1)Jedis是Redis的Java客户端,提供了java对于redis的常用操作。Jedis连接池设计基于apache commons-pool原生库,仅作了简单的封装。

Jedis操作步骤如下:

i.获取Jedis实例需要从JedisPool中获取;

ii.用完Jedis实例需要返还给JedisPool;

iii.如果Jedis在使用过程中出错,则也需要还给JedisPool;

2)引入依赖

<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>

3)spring配置JedisPool

<!-- 引入jedis配置文件 -->
<context:property-placeholder location="classpath:conf/properties/redis.properties"
                             ignore-unresolvable="true" />

<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxTotal">
<value>${redis.pool.maxActive}</value>
</property>
<property name="maxIdle">
<value>${redis.pool.maxIdle}</value>
</property>
<property name="testOnBorrow" value="true"/>
<property name="testOnReturn" value="true"/>
</bean>

<bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool"  scope="singleton">
<constructor-arg index="0" ref="jedisPoolConfig" />
<constructor-arg index="1">
<list>
<bean class="redis.clients.jedis.JedisShardInfo">
<constructor-arg name="host" value="${redis.uri}" />
</bean>
</list>
</constructor-arg>
</bean>

4)redis.properties配置

redis.pool.maxActive=200
redis.pool.maxIdle=50
redis.pool.minIdle=10
redis.pool.maxWaitMillis=20000
redis.pool.maxWait=300
redis.uri = redis://password@127.0.0.1:6379/0
redis.timeout=30000

5)将spring-redis.xml加入web.xml的context中

<context-param>
<param-name>contextConfigLocation</param-name>

<param-value>classpath:spring-redis.xml</param-value>

</context-param>

6)创建工具类来管理Jedis实例的生成和回收

@Repository("jedisDS")
public class JedisDataSourceImpl implements JedisDataSource {
private static final Logger LOG = LoggerFactory.getLogger(JedisDataSourceImpl.class);

@Autowired
   private ShardedJedisPool shardedJedisPool;

@Override
   public ShardedJedis getRedisClient() {
ShardedJedis shardJedis = null;
try {
shardJedis = shardedJedisPool.getResource();
return shardJedis;
} catch (Exception e) {
LOG.error("[JedisDS] getRedisClent error:" + e.getMessage());
if (null != shardJedis)
shardJedis.close();
}
return null;
}

@Override
   public void returnResource(ShardedJedis shardedJedis) {
shardedJedis.close();
}

@Override
   public void returnResource(ShardedJedis shardedJedis, boolean broken) {
shardedJedis.close();
}

7)编写具体的Jedis操作类

@Repository("redisClientTemplate")
public class RedisClientTemplate {
private static final Logger log = LoggerFactory.getLogger(RedisClientTemplate.class);

@Autowired
   private JedisDataSource redisDataSource;

public void disconnect() {
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
shardedJedis.disconnect();
}

/**
    * 设置单个值
    *
    * @param key
    * @param value
    * @return
    */
   public String set(String key, String value) {
String result = null;

ShardedJedis shardedJedis = redisDataSource.getRedisClient();
if (shardedJedis == null) {
return result;
}
boolean broken = false;
try {
result = shardedJedis.set(key, value);
} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

/**
    * 获取单个值
    *
    * @param key
    * @return
    */
   public String get(String key) {
String result = null;
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
if (shardedJedis == null) {
return result;
}

boolean broken = false;
try {
result = shardedJedis.get(key);

} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

public Boolean exists(String key) {
Boolean result = false;
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
if (shardedJedis == null) {
return result;
}
boolean broken = false;
try {
result = shardedJedis.exists(key);
} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

public String type(String key) {
String result = null;
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
if (shardedJedis == null) {
return result;
}
boolean broken = false;
try {
result = shardedJedis.type(key);

} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

/**
    * 在某段时间后失效
    *
    * @param key
    * @param seconds
    * @return
    */
   public Long expire(String key, int seconds) {
Long result = null;
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
if (shardedJedis == null) {
return result;
}
boolean broken = false;
try {
result = shardedJedis.expire(key, seconds);

} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

/**
    * 在某个时间点失效
    *
    * @param key
    * @param unixTime
    * @return
    */
   public Long expireAt(String key, long unixTime) {
Long result = null;
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
if (shardedJedis == null) {
return result;
}
boolean broken = false;
try {
result = shardedJedis.expireAt(key, unixTime);

} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

public Long ttl(String key) {
Long result = null;
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
if (shardedJedis == null) {
return result;
}
boolean broken = false;
try {
result = shardedJedis.ttl(key);

} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

public boolean setbit(String key, long offset, boolean value) {

ShardedJedis shardedJedis = redisDataSource.getRedisClient();
boolean result = false;
if (shardedJedis == null) {
return result;
}
boolean broken = false;
try {
result = shardedJedis.setbit(key, offset, value);
} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

public boolean getbit(String key, long offset) {
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
boolean result = false;
if (shardedJedis == null) {
return result;
}
boolean broken = false;

try {
result = shardedJedis.getbit(key, offset);
} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

public long setRange(String key, long offset, String value) {
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
long result = 0;
if (shardedJedis == null) {
return result;
}
boolean broken = false;
try {
result = shardedJedis.setrange(key, offset, value);
} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

public String getRange(String key, long startOffset, long endOffset) {
ShardedJedis shardedJedis = redisDataSource.getRedisClient();
String result = null;
if (shardedJedis == null) {
return result;
}
boolean broken = false;
try {
result = shardedJedis.getrange(key, startOffset, endOffset);

} catch (Exception e) {
log.error(e.getMessage(), e);
broken = true;
} finally {
redisDataSource.returnResource(shardedJedis, broken);
}
return result;
}

8)在业务代码里加载RedisClientTemplate.class提供的方法


二.明日计划

继续整理任务6代码,完成扫尾工作.


三.遇到问题

暂无.


四.收获

以上.


进度:向师兄社情,延期一天提交任务.







返回列表 返回列表
评论

    分享到