发表于: 2017-06-30 21:59:46
1 1184
今日完成:
项目添加memcache
压测JSP
明日计划:
- 部署两台WEB,使用Nginx的Upstream来做负载。重新压测。
- 将Memcache替换成Redis,重复以步骤。最后生成一份压测报告,同样的发布到自媒体里。
收获:
添加memcache步骤:
1.检查memcache客户端是否开启
在终端输入:lsof -i :11211 可以看到memcache进程。
如果没有进程在终端输入启动memcache命令:
memcached -d -p 11211 -u nobody -c 1024 -m 64
2.检查配置文件是否加载,缺少。
memcache需要的配置文件:
①memcache.properties、
#设置服务器地址
memcached.server=127.0.0.1:11211
#设置初始连接数
memcached.initConn=20
#设置最小连接数
memcached.minConn=10
#设置最大连接数
memcached.maxConn=50
#设置连接池维护线程的睡眠时间
memcached.maintSleep=3000
#设置是否使用Nagle算法(Socket的参数),如果是true在写数据时
memcached.nagle=false
#设置socket的读取等待超时时间
memcached.socketTO=100
②spring-mvc.xml下添加如下配置
<!--7.配置memcache-->
<bean id="memcachedPool" class="com.whalin.MemCached.SockIOPool"
factory-method="getInstance" init-method="initialize" destroy-method="shutDown">
<constructor-arg>
<value>memCachedPool</value>
</constructor-arg>
<property name="servers">
<list>
<value>${memcached.server}</value>
</list>
</property>
<property name="initConn">
<value>${memcached.initConn}</value>
</property>
<property name="minConn">
<value>${memcached.minConn}</value>
</property>
<property name="maxConn">
<value>${memcached.maxConn}</value>
</property>
<property name="maintSleep">
<value>${memcached.maintSleep}</value>
</property>
<property name="nagle">
<value>${memcached.nagle}</value>
</property>
<property name="socketTO">
<value>${memcached.socketTO}</value>
</property>
</bean>
<bean id="memCachedClient" class="com.whalin.MemCached.MemCachedClient">
<constructor-arg>
<value>memCachedPool</value>
</constructor-arg>
</bean>
然后引入memcache.properties文件
<context:property-placeholder location="classpath:properties/*"/>
上面是加载properties文件夹下所有配置文件
③添加jar包、com.danga的依赖总是加载失败,这里我用的是com.whalin依赖、
<dependency>
<groupId>com.whalin</groupId>
<artifactId>memcached-Java-Client</artifactId>
<version>3.0.2</version>
</dependency>
④web.xml、加载spring-mvc.xml配置文件。
⑤创建MemcachedUtils工具
package com.ptteng.login.util;
import com.whalin.MemCached.MemCachedClient;
import java.util.Date;
/**
* Created by shun on 2017/6/30.
*/
public class MemcachedUtils {
private static MemCachedClient cachedClient;
static {
if (cachedClient == null) {
cachedClient = new MemCachedClient("memCachedPool");
}
}
private MemcachedUtils() {
}
public static boolean set(String key, Object value) {
return setExp(key, value, null);
}
public static boolean set(String key, Object value, Date expire) {
return setExp(key, value, expire);
}
public static boolean setExp(String key, Object value, Date expire) {
boolean flag = false;
try {
flag = cachedClient.set(key, value, expire);
} catch (Exception e) {
}
return flag;
}
public static boolean add(String key, Object value) {
return addExp(key, value, null);
}
public static boolean add(String key, Object value, Date expire) {
return addExp(key, value, expire);
}
public static boolean addExp(String key, Object value, Date expire) {
boolean flag = false;
try {
flag = cachedClient.add(key, value, expire);
} catch (Exception e) {
}
return flag;
}
public static boolean replace(String key, Object value) {
return replaceExp(key, value, null);
}
/**
* 仅当键已经存在时,replace命令才会替换缓存中的键
*
* @param key
* @param value
* @param expire 过期时间 New Date(1000*10):十秒过期
* @return
*/
public static boolean replace(String key, Object value, Date expire) {
return replaceExp(key, value, expire);
}
/**
* 仅当键已经存在时,replace命令才会替换缓存中的键
*
* @param key
* @param value
* @param expire 过期时间 New Date(1000*10):十秒过期
* @return
*/
public static boolean replaceExp(String key, Object value, Date expire) {
boolean flag = false;
try {
flag = cachedClient.replace(key, value, expire);
} catch (Exception e) {
}
return flag;
}
/**
* get 命令用于检索与之前添加的键值对相关的值
*
* @param key
* @return
*/
public static Object get(String key) {
Object obj = null;
try {
obj = cachedClient.get(key);
} catch (Exception e) {
}
return obj;
}
/**
* 删除 memcached中的任何现有值。
*
* @param key
* @param expire
* @return
*/
public static boolean delete(String key, Date expire) {
return deleteExp(key, expire);
}
/**
* 删除memcached中的任何现有值
*
* @param key
* @param expire
* @return
*/
private static boolean deleteExp(String key, Date expire) {
boolean flag = false;
try {
flag = cachedClient.delete(key, expire);
} catch (Exception e) {
}
return flag;
}
/**
* 清理缓存中的所有键-值对
*
* @return
*/
public static boolean flushAll() {
boolean flag = false;
try {
flag = cachedClient.flushAll();
} catch (Exception e) {
}
return flag;
}
}
在service实现类中添加方法
@Service
public class excellence_stuServiceImpl implements excellence_stuService {
@Autowired
private excellence_stuDao excellence_stuDao;
public List<excellence_stu> getAll() {
List<excellence_stu>list;
if (MemcachedUtils.get("list") != null) {
list = (List<excellence_stu>) MemcachedUtils.get("list");
System.err.println("本次操作是从缓存中查询数据!");
return list;
}
list = excellence_stuDao.getAll();
boolean flag = MemcachedUtils.add("list", list);
System.err.println("本次操作是从数据库中查询数据,并向缓存中添加数据,添加结果为:"+flag);
return list;
}
}
⑥最关键的地方序列化实体类,没有这个,数据不能添加到缓存。在实体类方法名实现Serializable类
public class excellence_stu implements Serializable {
下面是操作成功示例
什么是序列化?
序列化:就是把一个对象用二进制的表示出来,这样才能把对象写入到输出流中,用来存储或传输, 类似说我第一个字节表示什么属性名词,第二个字节表示什么属性值,第几个字段表示有几个属性等的意思;
对应到项目中就是说,user这个bean实现了序列化之后,才能保存在memcached缓存中,
拓展:什么是反序列化?
反序列化:就是通过序列化后的字段还原成这个对象本身。但标识不被序列化的字段是不会被还原的。
如一般人员的密码信息等属性需要标识不被序列化。防止网络传输被窃取,特别是web程序
junit测试
在spring中添加测试方法需要在类名上加上这个两个
@RunWith(SpringJUnit4ClassRunner.class) //使用junit4进行测试
@ContextConfiguration({"classpath:spring/spring-mvc.xml"}) //加载配置文件
压测JSP
未添加缓存:直接卡在这不动了
添加缓存后:效果非常明显,但是cpu率占用特别高
问题:
一.clean
在IDEA里修改配置文件路径后,有时候不会自动加载,比如jdbc.properties这些。这时需要先clean一下,路径就加载成功了。最近经常用到这个操作,删除类后也需要clean一遍。
二.序列化
一下午就解决这个bug了,配置文件,jar包,添加缓存方法等都没问题,但是数据就是存不到缓存里,经志荣大佬指点,发现是没有实体类没有序列化的原因。
三、无法访问页面
发现一个奇怪的问题 经过多次尝试发现,启动memcaceh缓存后,只能访问一个controller类里的页面,访问第二个controller类会报错。关掉memcaceh进程后两个都可以正常访问。
重启memcache进程,访问list页面后再访问home页面就会出错
HTTP ERROR 500
Problem accessing /home. Reason:
Server Error
Caused by:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.apache.tiles.request.render.CannotRenderException: ServletException including path '/WEB-INF/layout/template.jsp'.
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:687)
重启memcache进程,访问home页面后再访问list页面就会出错
HTTP ERROR 500
Problem accessing /list. Reason:
Server Error
Caused by:
org.apache.jasper.JasperException: An exception occurred processing JSP page /WEB-INF/Student/list.jsp at line 68
65: <c:forEach items="${list}" var="l">
66: <tr>
67: <td>${l.id }</td>
68: <td>${l.stu_name }</td>
69: <td>${l.sign}</td>
70: <td>${l.stu_school}</td>
71: <td>${l.stu_introducer}</td>
Stacktrace:
at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:568)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:470)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:403)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:347)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:751)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:566)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:143)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:596)
评论