Memcached是高性能的KV格式(Key/Value)数据缓存服务器;
Memcached的特特点:
协议简单;基于libevent事件处理;基于内存完成数据存储,LRU算法;Memcached互不通信的集群,分布式集群;
安装Memcached:

yum install memcached
安装的文件数量也很少:

配置文件/etc/sysconfig/memcached:

memcached的其他选项,可以使用man 查看,可以在上面的配置文件中的OPTIONS中增加
memcached的服务启动单元文件如下:

其他配置选项在OPTIONS中写成 "-U 11222"形式
memcached的常用选项说明:
-l <ip_addr>:指定进程监听的地址;
-d: 以服务模式运行;
-u <username>:以指定的用户身份运行memcached进程;
-m <num>:用于缓存数据的最大内存空间,单位为MB,默认为64MB;
-c <num>:最大支持的并发连接数,默认为1024;
-p <num>: 指定监听的TCP端口,默认为11211;
-U <num>:指定监听的UDP端口,默认为11211,0表示关闭UDP端口;
-t <threads>:用于处理入站请求的最大线程数,仅在memcached编译时开启了支持线程才有效;
-f <num>:设定Slab Allocator定义预先分配内存空间大小固定的块时使用的增长因子;
-M:当内存空间不够使用时返回错误信息,而不是按LRU算法利用空间;
-n: 指定最小的slab chunk大小;单位是字节;
-S: 启用sasl进行用户认证;
memcached的工具:memcached-tool
启动memcached:systemctl start memcached
查看启动结果:ss -tunlp

连接memcached:使用telnet
telnet localhost 11211
memcached的命令:
set、add 、replace、append、prepend、get、delete、incr/decr、flush_all、stats、quit等
set key flags exptime bytes [noreply]
value
参数说明如下:
key:键值 key-value 结构中的 key,用于查找缓存值。
flags:可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息 。
exptime:在缓存中保存键值对的时间长度(以秒为单位,0 表示永远)
bytes:在缓存中存储的字节数
noreply(可选): 该参数告知服务器不需要返回数据
value:存储的值(始终位于第二行)(可直接理解为key-value结构中的value)
set命令中指定bytes是多少,value就要输入多少。
memcached是一个旁挂式缓存,客户端负责读写memcached,如果没有命中,由客户端自己去后端获取,而不是由memcached代理去获取。
内存存储:
slab allocation:整理内存以进行复用;
slab allocator
page:分配给slab用于再次分割为chunk的内存空间
chunk:用于缓存对象的空间
slab class:特定大小的chunk组合而成的组;
chunk --> slab class --> page
增长因子,-f <factor>,相邻chunk的大小之比:

memcached-tool工具查看状态的字段说明:

#:slab class的编号;
Item_Size:Chunk大小;
Max_age:缓存对象的生存时间;
Pages:分配给slab的内存页数;
Count:slab内的记录数;
Full?:slab是否仍有空闲chunk;
Evicted、Evict_Time、OOM:与LRU回收有关的数据;

分布式机制:
互不通信的分布式集群;
session会话保持之session服务器方案 :多台tomcat通过memcached共享缓存session
前提:
两台tomcat节点:192.168.61.128、192.168.61.129
两台memcached节点:192.168.61.130、192.168.61.131
一个负载均衡节点,使用nginx:192.168.61.130
此方案需要用到一个组件:msm ------ memcached-session-manager,是一个java类,tomcat容器借助此类将session保存到memcached服务器中。
下载如下jar文件至各tomcat节点的tomcat安装目录下的lib目录中,其中的{version}要换成你所需要的版本号,tc{6,7,8}要换成与tomcat版本相同的版本号。
memcached-session-manager-${version}.jar : 核心包
memcached-session-manager-tc{6,7,8}-{version}.jar : Tomcat 版本适配包
spymemcached-${version}.jar : 序列化工具
msm-javolution-serializer-${version}.jar
javolution-${version}.jar

将以上文件复制到$CATALINA_HOME/lib/目录下;
分别在两个tomcat上的Host中定义一个测试用的context容器,并创建一个会话管理器。context使用前面实验的例子,去掉集群的配置:

启动两个memcached,测试访问。
测试失败,添加上<Manager />这个标签,访问网页就不成功,调试很久,放弃。
出现的问题:多虚拟机反代问题、memcached的问题
关于tomcat多虚拟主机的设置问题,在默认配置上,增加了一个host设置:
<Engine name="Catalina" defaultHost="localhost" jvmRoute="Tomcat1">
<!--For clustering, please take a look at documentation at:
/docs/cluster-howto.html (simple how to)
/docs/config/cluster.html (reference documentation) -->
<!--
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
-->
<!-- Use the LockOutRealm to prevent attempts to guess user passwords
via a brute-force attack -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
<Host name="web1.test.com" appBase="/var/webapps" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="ROOT" reloadable="true">
<!-- <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
memcachedNodes="n1:192.168.61.130:11211,n2:192.168.61.131:11211"
failoverNodes="n1"
requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
/> -->
</Context>
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="/var/logs"
prefix="web1_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
Engine标签中设置的defaultHost=localhost,默认就是tomcat的首页,即$CATALINNA_HOME/webapps/ROOT/对应的应用,用ip地址访问时,给出的是这个页面。
同时设置了name=web1.test.com的虚拟主机,对用的主机的基目录为/var/webapps/,其下有ROOT目录,当访问web1.test.com:8080时,默认返回的是/var/webapps/ROOT/中的index.jsp,浏览器单独访问这两种地址,结果正确。
然后使用Nginx做反代:nginx的配置
user nginx;
worker_processes 2;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
upstream tmctsrv {
server web1.test.com:8080;
server web2.test.com:8080;
}
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
location / {
proxy_pass http://tmctsrv/;
}
}
proxy_cache_path /cache/nginx/ levels=1:1 keys_zone=mycache:16m;
fastcgi_cache_path /cache/fastcgi/ levels=1:2 keys_zone=fastcache:10m inactive=3m max_size=256m;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
按道理来说,其反代时使用负载均衡,轮询使用的server是tomcat中配置的虚拟主机的名字,即web1.test.com和web2.test.com,但是测试结果一直返回就是defaultHost,反代服务器上的hosts设置也正确。
JVM内存空间

JVM HEAP内存空间:

新生代(包括eden和survivor)
新生区(eden):初创对象
存活区(survivor):步入成熟期的初创对象,又分为to和from两个区
from:ss1,经过了eden或to期间还没有失效的对象,会被移到此区,
to :ss2,经过了eden或from期间还没有失效的对象,会被移到此区
老年代(old):经过了新生区的对象,即超过一定时间还没有失效的对象区。
持久代(perm):永远不会被垃圾回收的对象区。

垃圾回收器:针对HEAP区进行垃圾回收,不同代回收机制,即回收算法不同
新生代回收: Minor GC
老年代回收:Major GC(FULL GC)



可以看出,对于Minor GC,每次垃圾回收,新生代区一共三个分区eden、from、to只有一个区域有对象,或是from区或是to区,eden区回收后一定是空的,eden区的对象可能移动到from、to或old区,from可能移动到to或old,to可能移动到from或old。
Major GC的回收算法:

先扫描,打标记,然后一次性处理。
由上面的JVM HEAP内存结构,对tomcat进行调优时,就是调整这些区域大小,对应的就是一堆参数的配置。
堆内存空间的调整参数:
-Xmx:新生代和老年代总共可用的最大空间
-Xms:二者初始空间之和
-XX:NewSize :新生代初始空间
-XX:MaxNewSize:新生代的最大空间
-XX:MaxPermSize:持久代最大空间
-XX:PermSzie:持久代初始空间
可以看到,没有对old的配置,但是old的值可以通过-Xmx、-Xms、-XX:NewSize、-XX:MaxNewSize计算就能得到。
如果不显式配置,系统默认有一个新生代、老年代的分配比例和新生代中三个子分区的分配比例。
对tomcat而言:
catalina.sh(/usr/local/tomcat/bin/)中有两个环境变量:
CATALINA_OPTS:仅对启动运行tomcat实例的java虚拟机有效;
JAVA_OPTS:对本机上的所有java虚拟机有效;
JAVA性能监控工具:
问题:OutOfMemoryError:内存不足,可能的原因包括:
内存泄露
线程死锁
所竞争(Lock Contention)
Java消耗过多的CPU
工具:(在/usr/java/latest/bin目录中)

jps(java virtual machine process status tool):监控jvm进程状态信息
jps [options] [hostid] ,不带参数显示所有的JAVA进程
-m:输出传入main方法的参数
-l:显示main类或jar的完全限定名称
-v:显示为
jstack:查看某个java线程内的线程堆栈信息;
jstack [options] pid
-l long listings:,输出完整的锁信息;
-m:混合模式,即会输出java堆栈及C/C++堆栈信息;
jmap(jvm memory map)和jhat(java heap analysis tool):
jmap [options] pid
-heap:查看详细堆内存空间使用状态信息
-histo:live:查看堆内存中的对象数目、大小统计结果;
jhat [options] pid

jstat:jvm统计监测工具
jstat -<option> [-t] [-h<lines>] <vmid> [<interval> [<count>]]
其中<option>为必须提供的选项,所有可用选项可使用jstat -option列出:
-class
-compiler
-gc
-gccapacity
-gccause
-gcmetacapacity
-gcnew
-gcnewcapacity
-gcold
-gcoldcapacity
-gcutil
-printcompilation
jstat -gc pid:垃圾回收状态

字段意义:
S0C、S1C、S0U、S1U:C表示容量,U表示已用量,即from和to区信息;
EC、EU:eden区域的容量和已用量;
OC,OU:老年区的容量和已用量
MC,MU:元空间的容量,已使用大小
CCSC,CCSU:压缩类的容量,压缩类已使用大小
YGC,YGCT:新生代的GC次数,耗时;
FGC,FGCT:FULL GC的次数,耗时
GCT:GC总耗时
系统查看结果多了MC、MU、CCSC和CCSU,没有了持久代的信息。
两个GUI工具:jconsole,jvisualvm(Java Visual VM)