发表于: 2017-10-22 23:48:35
1 747
一.今日完成
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代码,完成扫尾工作.
三.遇到问题
暂无.
四.收获
以上.
进度:向师兄社情,延期一天提交任务.
评论