发表于: 2018-01-27 11:38:09
3 579
今天完成的事情:
1.搞昨天没弄好的telnet
总是无法连接11211端口,让人非常的崩溃,直到碰到了一篇博客:
https://www.cnblogs.com/love540376/p/6473530.html
被这篇博客点醒了,应该是我的Memcached安装的不对,于是重新安装了Memcached,教程上面都有,按照教程一步步走下来终于能够访问11211端口了:
到了这个界面就ctrl+】
来到这个界面,再回车,来到这里:
好了。。。。可以使用这个东西了。。。真的是麻烦。
http://www.runoob.com/memcached/memcached-set-data.html
上面这个是使用教程,是memcached的常用命令,大家可以去搞一搞。
https://www.cnblogs.com/jeffwongishandsome/archive/2011/11/06/2238265.html
这篇的命令也说得非常好
至此这个东西已经安装好了。
2.接下来就是使用这个东西了:在命令行界面使用当然非常尴尬,于是我找到了这篇教程:
http://blog.csdn.net/ycyk_168/article/details/11214175
按照这个教程一步步搞下来,结果遭遇了情况:我的测试类运行全部通过,但是没有任何数据打印到控制台,这可把我急坏了,怎么搞都不行。。
然后搞了好久突然意识到一个问题,就是我没有设置任何值它怎么会输出呢?
于是我加了个值。就成功了。。。传一下代码:
项目结构,省的后面的人再彷徨浪费时间
接下来是userbean:
package com.ceshi.model;
import java.io.Serializable;
public class UserBean implements Serializable {
private static final long serialVersionUID = 9174194101246733501L;
private String username;
private String password;
public UserBean(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((password == null) ? 0 : password.hashCode());
result = prime * result
+ ((username == null) ? 0 : username.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
UserBean other = (UserBean) obj;
if (password == null) {
if (other.password != null)
return false;
} else if (!password.equals(other.password))
return false;
if (username == null) {
if (other.username != null)
return false;
} else if (!username.equals(other.username))
return false;
return true;
}
@Override
public String toString() {
return "username:" + username + ",password:" + password;
}
}
然后是工具类:
package com.ceshi;
import com.danga.MemCached.MemCachedClient;
import com.danga.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);
}
}
然后是测试类:
package com.ceshi;
import com.ceshi.model.UserBean;
import org.junit.Assert;
import org.junit.Test;
public class MemcachedUtilTest {
@Test
public void testMemcached() {
MemcachedUtil.put("hello", "world", 60);
String hello = (String) MemcachedUtil.get("hello");
System.out.println(hello);
Assert.assertEquals("world", hello);
for(int i = 0; i < 100; ++i) {
UserBean userBean = new UserBean("Jason" + i, "123456-" + i);
MemcachedUtil.put("user" + i, userBean, 60);
Object obj = MemcachedUtil.get("user" + i);
System.out.println(obj);
Assert.assertEquals(userBean, obj);
}
}
}
我加上了两个输出语句。
接着是pom文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.ceshi</groupId>
<artifactId>memcached</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>memcached</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>com.danga</groupId>
<artifactId>memcached</artifactId>
<version>2.6.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>commons-pool</groupId>
<artifactId>commons-pool</artifactId>
<version>1.5.6</version>
</dependency>
</dependencies>
</project>
好的,就是这些东西了。
这个东西也比较简单(我的意思是代码的字面表达很清晰,不是说原理简单),一看就能理解是什么意思。
涉及到了新的知识点:
Assert.assertEquals("world", hello);
这个是junit的断言,用来检验和报错。语法如下:
Assert.assertEquals([String message],expected,actual)
参数说明:
message是个可选的消息,假如提供,将会在发生错误时报告这个消息。
expected是期望值,通常都是用户指定的内容。
actual是被测试的代码返回的实际值。
这样说很难理解,我下面举个栗子来说明一下:
可以看到,我在我的测试类里面加了一句代码,同样是hello这个键,对应的值我写了个xizi,那么运行结果:
可以看到输出的是xizi,我认为这是因为就近原则,然后继续看下面的报错,因为我们在测试类里面断言了hello对应的是world,而输出的是xizi,所以断言报错,期待的是wirld,事实是xizi。
这么一整大家应该都能明白这个断言是啥东西了吧,我认为这是一个检查的关卡。
最后,注意点:
第一、memcached是在服务器端的内存中缓存对象的,不是缓存或硬盘;
第二、memcached的pool可以关联多个server,
String[] servers = {"10.20.185.12:11001","10.20.185.25:11001"};
Integer[] weights = {3,7};
该配置表示30%的缓存在放在第一台服务器,70%的将放在第二台服务器,这样便可以充分利用不同服务器的内存了;
第三、我最困惑的是client是如何得到相应的pool的,后然看了点源码才知道是这样的。client是通过pool的name关联到某个pool的,上面的例子中在SockIOPool pool = SockIOPool.getInstance(); 和MemCachedClient client=<span new<="" span="" style="word-break: break-all;"> MemCachedClient();虽然都没写poolName,但就是新建了一个”default“的pool,然后client关联到了这个”default“的pool。当然我们在新建这两个对象时可以给定具体的poolName。
3.然后看任务要求,有点读不太懂,分析一波:
我的理解就是将首页(t10)的数据放到缓存中,然后从缓存中取出显示。进行压测。所以先压测一波没加缓存的:
于是设置了100线程1s启动循环2次:
可以看到吞吐量很低,而且响应时间很长。再看看TPS视图:
很低,接下来是用了缓存的:
不知道为啥用了缓存之后的页面打开要三分钟以上。。。很难受,正在致力于解决这个问题。。
目前推测是将数据放进缓存的时候出现了问题,于是将代码复原,重新加进缓存:
然后报错500:
Handler processing failed; nested exception is java.lang.VerifyError: Bad type on operand stack
去谷歌了一下,大概说是jar包的问题
然后更换了jar包,现在的报错是:
java.io.NotSerializableException
百度了一下是序列化失败,简直他妈的完美解决了我的问题
于是我加上接口,再次运行,通过我的日志,发现成功了!!!!!!!!!!!先上代码再上图:
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;
}
第一次登录肯定是没有缓存的,第二次就有了。哈哈哈哈,成功搞定。
那么就在这说说从头到尾的问题吧
一开始是请教了师兄,师兄告诉我是我的Memcached工具类有问题,于是我换了工具类,换了之后还是有问题,我百度之后更换了jar包,最后就是这个地方了,加上接口。那么完整的jar包其实只有一个,受之前教程毒害太重,浪费好多时间。在这里放一下jar:
<dependency>
<groupId>com.whalin</groupId>
<artifactId>Memcached-Java-Client</artifactId>
<version>3.0.2</version>
</dependency>
就这一个足矣。之前的教程让放四个,结果各种冲突。
然后是工具类:其实知识因为jar包换了,所以引入类发生了一点变化:
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);
}
}
我做了这些之后,在项目中加入缓存就成功了,很开心。
今天遇到的问题
上面都说到了,而且解决方法也都在上面。重点还是教程的选择,我就走了不少弯路。
今天的收获
Memcached的使用以及将数据加入缓存和从缓存中取出;telnet的使用,以及junit的断言的知识点
明天计划的事情
明天继续推进任务六,估计明天要开始搞redis了
最后,辛苦我英姿伟岸,风流倜傥,貌比潘安,剑眉星目的艳行大师兄审核日报。
评论