使用lsof处理文件恢复、句柄以及空间释放问题 - SegmentFault
曾经在生产上遇到过一个df 和 du出现的结果不一致的问题,为了排查到底是哪个进程占用了文件句柄,导致空间未释放,首先在linux上面,一切皆文件,这个问题可以使用lsof这个BT的命令来处理(这个哈还可以来查询文件句柄泄露问题,应用程序的进程未关闭文件句柄)
1.文件句柄以及空间释放问题
- 注:在生产环境常见的问题就是,有维护人员或者开发同事使用tail命令实时查看日志。然后另外的人使用rm命令删除,这有就好导致磁盘空间不会真正的释放,因为你要删除的文件,还有进程在使用,文件句柄没有释放,即tail
模拟场景1:
你创建一个文件testfile
touch testfile
然后使用tail命令一直查看
tail testfile
这个时候另外一个同事使用rm命令来删除了该文件
rm testfile
正式使用lsof命令排查
如果你知道文件名,那就可以直接使用如下命令
lsof |grep testfile
但是如果你不知道是哪个文件,或者是很多文件都有这样的情况,那你需要使用如下命令
lsof |grep deleted 注:这个deleted表示该已经删除了的文件,但是文件句柄未释放,这个命令会把所有的未释放文件句柄的进程列出来
注:有些系统你没有配置环境变量的话,直接lsof是会报错没有该命令,你可以直接/usr/bin/lsof 或者是/usr/sbin/lsof,根据你的系统环境自己查看
然后上面命令出来的结果会出来如下结果
root 123 12244 0 14:47 pts/1 01:02:03 tail testfile
然后你可以使用kill 命令来释放文件句柄从而释放空间
kill 123
2. 文件恢复问题
在说明问题之前,先介绍下一些文件的基本概念:
- 文件实际上是一个指向inode的链接, inode链接包含了文件的所有属性, 比如权限和所有者, 数据块地址(文件存储在磁盘的这些数据块中). 当你删除(rm)一个文件, 实际删除了指向inode的链接, 并没有删除inode的内容. 进程可能还在使用. 只有当inode的所有链接完全移去, 然后这些数据块将可以写入新的数据.
- proc文件系统可以协助我们恢复数据. 每一个系统上的进程在/proc都有一个目录和自己的名字, 里面包含了一个fd(文件描述符)子目录(进程需要打开文件的所有链接). 如果从文件系统中删除一个文件, 此处还有一个inode的引用:
/proc/进程号/fd/文件描述符
- 你需要知道打开文件的进程号(pid)和文件描述符(fd). 这些都可以通过lsof工具方便获得, lsof的意思是”list open files, 列出(进程)打开的文件”. 然后你将可以从/proc拷贝出需要恢复的数据.
1.创建一个测试文件并且备份下,方面后续验证
touch testfile cp testfile testfile.backup.2014
2.查看文件的相关信息
stat testfile File: 'testfile' Size: 343545 Blocks: 241 IO Block: 4096 regular file Device: fd00h/64768d Inode: 361579 Links: 1 Access: (0664/-rw-rw-r–) Uid: ( 505/ zhaoke) Gid: ( 505/ zhaoke) Access: 2014-11-09 15:00:38.000000000 +0800 Modify: 2014-11-09 15:00:34.000000000 +0800 Change: 2014-04-09 15:00:34.000000000 +0800
没问题, 继续下面工作:
3.删除文件
rm testfile
4.查看文件
ls -l testfile ls: testfile: No such file or directory
stat testfile stat: cannot stat 'testfile': No such file or directory
testfile文件删除了,但不要终止仍在使用文件的进程, 因为一旦终止, 文件将很难恢复.
现在我们开始找回数据之旅,先使用lsof命令查看下
lsof | grep testfile tail 5317 root 4r REG 253,0 343545 361579 /root/testfile (deleted)
-
第一个纵行是进程的名称(命令名), 第二纵行是进程号(PID), 第四纵行是文件描述符
-
现在你知道5317进程仍有打开文件, 文件描述符是4. 那我们开始从/proc里面拷贝出数据.
-
你可能会考虑使用cp -a, 但实际上没有作用, 你将拷贝的是一个指向被删除文件的符号链接:
ls -l /proc/5317/fd/4 lr-x—— 1 root root 64 09 15:00 /proc/5317/fd/4 -> /root/testfile (deleted)
使用cp -a命令测试恢复
cp -a /proc/5317/fd/4 testfile.backup
使用ls命令来查看
ls -l testfile.backup lrwxrwxrwx 1 root root 29 09 15:02 testfile.backup -> /roor/testfile (deleted)
通过上面的命令我们发现,使用cp -a命令,其恢复的是一个指向被删除文件的符号链接
使用file命令分别查看文件和文件描述符
- 1.查看文件
file testfile.backup testfile.backup: broken symbolic link to '/root/testfile (deleted)'
- 2.查看文件描述符
file /proc/5317/fd/4 /proc/5317/fd/4: broken symbolic link to '/root/myfile (deleted)'
根据上面的file结果,可以使用cp拷贝出文件描述符数据到一个文件中,如下:
cp /proc/5317/fd/4 testfile.new
使用上面的命令恢复后,我们需要最终确认一下文件是否恢复,以及文件内容是否正确:
ls -l testfile.new
然后把新旧的两个文件对比
diff testfile.new myfile.backup
Linux服务器中高负载现象故障排查指南 - 51CTO.COM
技术支持分析师们常常接到用户对服务器高负载的控诉。事实上cPanel软件及其安装的应用很少引发服务器高负载情况。服务器拥有者、系统管理员或者服务器供应商应当对高负载状况进行初步调查,并在确认情况复杂后再向分析人士求助。
服务器高负载因何而起?
下列项目的过度使用会直接导致高负载问题:
- CPU
- 内存(包括虚拟内存)
- 磁盘I/O
该如何检查这些项目?
这取决于大家是要审查当前资源使用情况还是历史资源使用情况。当然,在本文中我们将从这两方面进行探讨。
关于sar的简要说明
历史资源使用情况可通过sar工具查看,该工具在默认情况下应该通过sysstat软件包安装在所有cPanel服务器当中。只要通过cron命令对sysstat进行周期性执行(/etc/cron.d/sysstat),服务器的运行状态数据就会被收集起来。如果cron没有运行,sysstat将无法收集历史统计结果。
要在sar中查看历史资源使用情况,我们必须为文件提供与统计数据相符的路径。
举例来说,如果大家打算查看本月23号以来服务器的平均负载状况,可以运行以下命令:
代码:
- [user@host ~]$ sar -q -f /var/log/sa/sa23
以上命令中的-q用于获取平均负载信息,而-f则用于指定sar从哪个文件中获取信息。请注意,sar可能无法使用一周之前乃至更早的运行信息。
如果大家打算查看当前日期的统计信息,则不必为其指令具体时间。输入以下命令即可显示今天的平均负载情况:
代码:
- [user@host ~]$ sar -q
我们强烈建议大家阅读sar说明文档:
代码:
- [user@host ~]$ man sar
它所提供的统计信息能够帮助我们确切掌握服务器的运行状态。
当前CPU使用情况
运行top,并在Cpu(s)一行中检查%id部分所显示的闲置CPU百分比。该数字越高结果越好,说明CPU的工作负载不强。处于99%闲置状态下的CPU几乎没有处理任何实际任务,而处于1%闲置状态下的CPU则意味着接近满载。
代码:
- [user@host ~]$ top c
提示:可加写P根据消耗CPU资源的多少对进程加以分类。
历史CPU使用情况
查看“%idle”列:
代码:
- [user@host ~]$ sar -p
当前内存使用情况
代码:
- [user@host ~]$ free -m
提示:运行top c并加写M可查看哪个进程占用的内存量最大。
历史内存使用情况
根据sar版本的不同,命令内容也有所区别。早期版本通过添加“-r”参数显示内存使用百分比与虚拟内存使用百分比,但新版本则改用“-s”参数显示虚拟内存使用百分比。
Check %memused and %swpused:
代码:
- [user@host ~]$ sar -r
或者:
代码:
- [user@host ~]$ sar -r
代码:
- [user@host ~]$ sar -S
内存使用情况提示:服务器内存占用量较高的情况其实非常正常。这是因为内存的读写速度及效率远高于服务器磁盘,因此操作系统倾向于将内存作为缓冲机制预先载入数据,从而提高数据读取速度。
同样,内存使用百分比也并不是什么大问题(除非大家没有设置虚拟内存分区,但这也与内存本身无关)。大家真正需要关注的是虚拟内存使用百分比,因为只有在服务器的物理内存被全部占用后、虚拟内存才会接替而上发挥作用。这一数字越低,就说明服务器的运行状态越好。如果虚拟内存使用率为0%,则意味着我们的服务器能够完全利用物理内存执行任务。
那么虚拟内存使用率达到多少才算过高?这取决于大家自己的感觉。一般来说,如果虚拟内存使用率一直不高、那么我们的服务器的运行状态还是比较理想的。如果大家发现虚拟内存使用率随时间不断提升(例如由1%到7%再到32%),这就代表服务器上的某些进程正在疯狂吞噬内存,我们需要及时展开调查以了解具体情况(而不该直接安装更多内存)。一旦服务器用尽了所有物理内存与虚拟内存,那么整套系统的运行将变得极为缓慢,需要经过重启才能暂时恢复正常。
当前磁盘I/O使用情况
注意:这一项对于OpenVZ/Virtuozzo容器不起作用。
以下命令将以每秒一次的频率连续显示十次磁盘使用率统计。请大家关注显示结果中的%util列:
代码:
- [user@host ~]$ iostat -x 1 10
历史磁盘I/O使用情况
代码:
- [user@host ~]$ sar -d
优秀的系统管理员能够准确把握服务器负载的基准线,并在当前负载超出基准时立即做出判断。这样做的主要目的(除了防止服务器陷入半瘫痪并不得不重新启动之外)是为了及时了解负载高企时服务器正在运行哪些项目。快速反应能帮助大家在发现问题后第一时间进行故障排查。
如果服务器负载过高的状况出现在凌晨两点到四点之间,那么正在熟睡中的我们肯定无法马上展开调查。虽然sar会一直守护在服务器身边,帮我们收集这段时间内到底哪些资源的使用率居高不下,但却无法揭示问题出现的实际原因。引发负载过高的原因多种多样,其中包括DoS攻击、垃圾邮件攻击、php脚本设计不当、网络蜘蛛在绘制网络图谱时太过积极、硬件故障、针对用户MySQL数据库的磁盘写入量暴增等等。
好消息是,大家可以利用工具收集这些信息,并在负载过高后将结果自动发送过来。如何实现?从进程列表入手:
代码:
- [user@host ~]$ ps auxwwwf
我创建了一个shell脚本,以我曾经管理过的服务器上的一套perl脚本为基础。这套脚本与其它服务器监控工具(例如Nagios)配合起来给我的工作带来诸多便利。它能检查六种不同项目(下面将详细介绍),并在进程列表中的条目超出阈值时向我发送邮件通知。
注意:cPanel公司对该脚本的开发、维护或技术支持不承担责任。请不要就这款脚本提出服务申请。如果您在使用中遇到任何问题,请到相关论坛上发帖或请教有经验的系统管理员。cPanel不提供与此脚本相关的任何支持。
它所检查的具体资源对象如下:
- 一分钟平均负载
- 虚拟内存使用数量(单位为KB)
- 内存使用数量(单位为KB)
- 每秒接收数据包数量
- 每秒发出数据包数量
- 进程总数
如何使用脚本
要自动运行此脚本,大家需要设置一项cron任务并根据实际情况设定运行频率。我发现每五分钟运行一次是个不错的选择。该脚本无需使用root身份运行,既然如此我们也就不必为其分配高权限。
如果上述监控资源对象中的某一项超过用户自定义的阈值,脚本会自动发送一封电子邮件,其中包含当前进程列表内容。
电子邮件的主题行如下所示:
代码:
- server.example.com [L: 35] [P: 237] [Swap Use: 1% ] [pps in: 54 pps out: 289]
下面我们一一解释其中的条目:
- L代表一分钟平均负载
- P代表当前进程列表中的进程数量
- Swap Usage代表虚拟内存使用百分比
- pps in代表每秒接收数据包数量
- pps out代表每秒发出数据包数量
脚本使用前的注意事项
重要事项:大家需要根据自己的理解来调整脚本中的数值。完美的默认值设定并不存在,因为不同的服务器环境在实际运行中所应遵循的标准也不一样。举例来说,拥有十六个CPU核心的服务器在一分钟平均负载方面肯定要高于只拥有一个CPU核心的服务器。
注意:大家需要将自己的电子邮箱地址添加到EMAIL变量当中,如下所示:
代码:
- EMAIL=you@example.com
以下五项也需要根据实际情况加以调整:
- MAX_LOAD
- MAX_SWAP_USED
- MAX_MEM_USED
- MAX_PPS_OUT
- MAX_PPS_IN
代码:
- #!/bin/sh
- export PATH=/bin:/usr/bin
- ##########################################################################
- # #
- # Copyright Jeff Petersen, 2009 - 2013 #
- # #
- # This program is free software: you can redistribute it and/or modify #
- # it under the terms of the GNU General Public License as published by #
- # the Free Software Foundation, either version 3 of the License, or #
- # (at your option) any later version. #
- # #
- # This program is distributed in the hope that it will be useful, #
- # but WITHOUT ANY WARRANTY; without even the implied warranty of #
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
- # GNU General Public License for more details. #
- # #
- # You should have received a copy of the GNU General Public License #
- # along with this program. If not, see <http://www.gnu.org/licenses/>. #
- # #
- ##########################################################################
- ###############################################################################
- # START USER CONFIGURABLE VARIABLES
- ###############################################################################
- EMAIL="[email protected]"
- # 1 minute load avg
- MAX_LOAD=3
- # kB
- MAX_SWAP_USED=1000
- # kB
- MAX_MEM_USED=500000
- # packets per second inbound
- MAX_PPS_IN=2000
- # packets per second outbound
- MAX_PPS_OUT=2000
- # max processes in the process list
- MAX_PROCS=400
- ###############################################################################
- # END USER CONFIGURABLE VARIABLES
- ###############################################################################
- IFACE=`grep ETHDEV /etc/wwwacct.conf | awk '{print $2}'`
- if [[ "$IFACE" =~ "venet" ]] ; then
- IFACE=venet0
- fi
- IFACE=${IFACE}:
- ###############################################################################
- # 1 min load avg
- ###############################################################################
- ONE_MIN_LOADAVG=`cut -d . -f 1 /proc/loadavg`
- echo "1 minute load avg: $ONE_MIN_LOADAVG"
- ###############################################################################
- # swap used
- ###############################################################################
- SWAP_TOTAL=`grep ^SwapTotal: /proc/meminfo | awk '{print $2}'`
- SWAP_FREE=`grep ^SwapFree: /proc/meminfo | awk '{print $2}'`
- let "SWAP_USED = (SWAP_TOTAL - SWAP_FREE)"
- echo "Swap used: $SWAP_USED kB"
- ###############################################################################
- # mem used
- ###############################################################################
- MEM_TOTAL=`grep ^MemTotal: /proc/meminfo | awk '{print $2}'`
- MEM_FREE=`grep ^MemFree: /proc/meminfo | awk '{print $2}'`
- let "MEM_USED = (MEM_TOTAL - MEM_FREE)"
- echo "Mem used: $MEM_USED kB"
- ###############################################################################
- # packets received
- ###############################################################################
- PACKETS_RX_1=`grep $IFACE /proc/net/dev | awk '{print $2}'`
- sleep 2;
- PACKETS_RX_2=`grep $IFACE /proc/net/dev | awk '{print $2}'`
- let "PACKETS_RX = (PACKETS_RX_2 - PACKETS_RX_1) / 2"
- echo "packets received (2 secs): $PACKETS_RX"
- ###############################################################################
- # packets sent
- ###############################################################################
- PACKETS_TX_1=`grep $IFACE /proc/net/dev | awk '{print $10}'`
- sleep 2;
- PACKETS_TX_2=`grep $IFACE /proc/net/dev | awk '{print $10}'`
- let "PACKETS_TX = (PACKETS_TX_2 - PACKETS_TX_1) / 2"
- echo "packets sent (2 secs): $PACKETS_TX"
- let "SWAP_USED = SWAP_TOTAL - SWAP_FREE"
- if [ ! "$SWAP_USED" == 0 ] ; then
- PERCENTAGE_SWAP_USED=`echo $SWAP_USED / $SWAP_TOTAL | bc -l`
- TOTAL_PERCENTAGE=`echo ${PERCENTAGE_SWAP_USED:1:2}%`
- else
- TOTAL_PERCENTAGE='0%'
- fi
- ###############################################################################
- # number of processes
- ###############################################################################
- MAX_PROCS_CHECK=`ps ax | wc -l`
- send_alert()
- {
- SUBJECTLINE="`hostname` [L: $ONE_MIN_LOADAVG] [P: $MAX_PROCS_CHECK] [Swap Use: $TOTAL_PERCENTAGE ] [pps in: $PACKETS_RX pps out: $PACKETS_TX]"
- ps auxwwwf | mail -s "$SUBJECTLINE" $EMAIL
- exit
- }
- if [ $ONE_MIN_LOADAVG -gt $MAX_LOAD ] ; then send_alert
- elif [ $SWAP_USED -gt $MAX_SWAP_USED ] ; then send_alert
- elif [ $MEM_USED -gt $MAX_MEM_USED ] ; then send_alert
- elif [ $PACKETS_RX -gt $MAX_PPS_IN ] ; then send_alert
- elif [ $PACKETS_TX -gt $MAX_PPS_OUT ] ; then send_alert
- elif [ $MAX_PROCS_CHECK -gt $MAX_PROCS ] ; then send_alert
- fi
需要注意的是,进程列表的输出内容中包含一些有用的数列,涉及各个进程的CPU与内存使用情况:
- %CPU
- %MEM
- VSZ
- RSS
- TIME (显示一个进程的存在时间)
我们可以通过多种方式剖析服务器负载高企的原因。下面我们列出几项常用方案--仅供参考,并不全面:
- 利用mysqladmin processlist (或者简写为'mysqladmin pr')检查MySQL进程列表
- 利用mytop检查MySQL进程列表
- 查阅日志文件。了解服务器自身的反馈意见也很重要。您的服务器是否遭遇暴力破解?
- 运行dmesg以检查可能存在的硬件故障
- 利用netstat查看服务器连接
下面则是值得关注的日志文件及其保存路径:
- 系统日志: /var/log/messages, /var/log/secure
- SMTP日志: /var/log/exim_mainlog, /var/log/exim_rejectlog, /var/log/exim_paniclog
- POP3/IMAP日志: /var/log/maillog
- Apache日志: /usr/local/apache/logs/access_log, /usr/local/apache/logs/error_log, /usr/local/apache/logs/suexec_log, /usr/local/apache/logs/suphp_log
- 网站日志: /usr/local/apache/domlogs/ (use this to find sites with traffic in the last 60 seconds: find -maxdepth 1 -type f -mmin -1 | egrep -v 'offset|_log$')
- Cron日志: /var/log/cron
大家也可以在评论栏中反馈您在工作中遇到的问题、对本篇文章的评论及其它任何希望与朋友们分享的信息。作为一篇独立的指导性文章,我们不可避免会存在遗漏或者疏忽,期待您提出宝贵意见、也希望大家能从中受到一点启发。
原文链接:
http://forums.cpanel.net/f34/troubleshooting-high-server-loads-linux-servers-319352.html
为最佳性能调优 Nginx - 博客 - 伯乐在线
配置:
1
2
|
cp /etc/nginx/nginx .conf /etc/nginx/nginx .conf.orig vim /etc/nginx/nginx .conf |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
# This number should be, at maximum, the number of CPU cores on your system. # (since nginx doesn't benefit from more than one worker per CPU.) # 这里的数值不能超过 CPU 的总核数,因为在单个核上部署超过 1 个 Nginx 服务进程并不起到提高性能的作用。 worker_processes 24; # Number of file descriptors used for Nginx. This is set in the OS with 'ulimit -n 200000' # or using /etc/security/limits.conf # Nginx 最大可用文件描述符数量,同时需要配置操作系统的 "ulimit -n 200000",或者在 /etc/security/limits.conf 中配置。 worker_rlimit_nofile 200000; # only log critical errors # 只记录 critical 级别的错误日志 error_log /var/log/nginx/error .log crit # Determines how many clients will be served by each worker process. # (Max clients = worker_connections * worker_processes) # "Max clients" is also limited by the number of socket connections available on the system (~64k) # 配置单个 Nginx 单个进程可服务的客户端数量,(最大值客户端数 = 单进程连接数 * 进程数 ) # 最大客户端数同时也受操作系统 socket 连接数的影响(最大 64K ) worker_connections 4000; # essential for linux, optmized to serve many clients with each thread # Linux 关键配置,允许单个线程处理多个客户端请求。 use epoll; # Accept as many connections as possible, after nginx gets notification about a new connection. # May flood worker_connections, if that option is set too low. # 允许尽可能地处理更多的连接数,如果 worker_connections 配置太低,会产生大量的无效连接请求。 multi_accept on; # Caches information about open FDs, freqently accessed files. # Changing this setting, in my environment, brought performance up from 560k req/sec, to 904k req/sec. # I recommend using some varient of these options, though not the specific values listed below. # 缓存高频操作文件的FDs(文件描述符/文件句柄) # 在我的设备环境中,通过修改以下配置,性能从 560k 请求/秒 提升到 904k 请求/秒。 # 我建议你对以下配置尝试不同的组合,而不是直接使用这几个数据。 open_file_cache max=200000 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 2; open_file_cache_errors on; # Buffer log writes to speed up IO, or disable them altogether # 将日志写入高速 IO 存储设备,或者直接关闭日志。 # access_log /var/log/nginx/access.log main buffer=16k; access_log off; # Sendfile copies data between one FD and other from within the kernel. # More efficient than read() + write(), since the requires transferring data to and from the user space. # 开启 sendfile 选项,使用内核的 FD 文件传输功能,这个比在用户态用 read() + write() 的方式更加高效。 sendfile on; # Tcp_nopush causes nginx to attempt to send its HTTP response head in one packet, # instead of using partial frames. This is useful for prepending headers before calling sendfile, # or for throughput optimization. # 打开 tcp_nopush 选项,Nginux 允许将 HTTP 应答首部与数据内容在同一个报文中发出。 # 这个选项使服务器在 sendfile 时可以提前准备 HTTP 首部,能够达到优化吞吐的效果。 tcp_nopush on; # don't buffer data-sends (disable Nagle algorithm). Good for sending frequent small bursts of data in real time. # 不要缓存 data-sends (关闭 Nagle 算法),这个能够提高高频发送小数据报文的实时性。 tcp_nodelay on; # Timeout for keep-alive connections. Server will close connections after this time. # 配置连接 keep-alive 超时时间,服务器将在超时之后关闭相应的连接。 keepalive_timeout 30; # Number of requests a client can make over the keep-alive connection. This is set high for testing. # 单个客户端在 keep-alive 连接上可以发送的请求数量,在测试环境中,需要配置个比较大的值。 keepalive_requests 100000; # allow the server to close the connection after a client stops responding. Frees up socket-associated memory. # 允许服务器在客户端停止发送应答之后关闭连接,以便释放连接相应的 socket 内存开销。 reset_timedout_connection on; # send the client a "request timed out" if the body is not loaded by this time. Default 60. # 配置客户端数据请求超时时间,默认是 60 秒。 client_body_timeout 10; # If the client stops reading data, free up the stale client connection after this much time. Default 60. # 客户端数据读超时配置,客户端停止读取数据,超时时间后断开相应连接,默认是 60 秒。 send_timeout 2; # Compression. Reduces the amount of data that needs to be transferred over the network # 压缩参数配置,减少在网络上所传输的数据量。 gzip on; gzip_min_length 10240; gzip_proxied expired no-cache no-store private auth; gzip_types text /plain text /css text /xml text /javascript application /x-javascript application /xml ; gzip_disable "MSIE [1-6]." ; |
1
|
vim /etc/sysctl .conf |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
# Increase system IP port limits to allow for more connections # 调高系统的 IP 以及端口数据限制,从可以接受更多的连接 net.ipv4.ip_local_port_range = 2000 65000 net.ipv4.tcp_window_scaling = 1 # number of packets to keep in backlog before the kernel starts dropping them # 设置协议栈可以缓存的报文数阀值,超过阀值的报文将被内核丢弃 net.ipv4.tcp_max_syn_backlog = 3240000 # increase socket listen backlog # 调高 socket 侦听数阀值 net.core.somaxconn = 3240000 net.ipv4.tcp_max_tw_buckets = 1440000 # Increase TCP buffer sizes # 调大 TCP 存储大小 net.core.rmem_default = 8388608 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 65536 16777216 net.ipv4.tcp_congestion_control = cubic |
每次修订配置之后都需要执行以下命令使之生效.
1
|
sysctl -p /etc/sysctl .conf
|
10部史上票房最高的动画片 - 电影 - 英语学习站_爱词霸
《超能陆战队》在今年的奥斯卡颁奖典礼上斩获最佳动画长片奖,该片在美国狂揽2.2亿美元票房。这个数字固然不错,但如果对照《财富》扣除通胀因素,重新发布的史上票房成绩最高的动画电影榜单,它真的不算什么。那么,史上票房最高的动画电影是哪一部呢?
Big Hero 6 was the big winner of the Academy Award for Best Animated Feature on Oscar night Sunday. The story of an inflatable personal healthcare robot with a heart of gold, it's already taken in $220 million at the domestic box office, according to Box Office Mojo, making it the 20th highest grossing animated movie of all time.
电影《超能陆战队》(Big Hero 6 )在今年的奥斯卡颁奖典礼上斩获最佳动画长片奖。据票房魔咒网统计,有一颗金子心的充气机器人大白凭借卖得一手好萌,在美国国内狂揽2.2亿美元票房,使这部影片成为有史以来票房收入第20高的动画电影。
All fine and good, but after you adjust box office totals for inflation, its haul is a lot less impressive. Fortune combed through Box Office Mojo's list of highest-grossing animated movies and adjusted their domestic totals for inflation, and some of the movies that now appear in the top 10 may be surprising. It's also worth noting that all box office totals are adjusted to 2014 dollars, because the federal Bureau of Labor Statistics, which tracks inflation, doesn't release its 2015 figures until the end of this week.
这个数字固然不错,但如果你把历年各大动画电影的票房收入用通胀率进行调整后,它就显得不那么犀利了。《财富》选取了票房魔咒网给出的史上票房成绩最高的几部动画电影,然后根据通胀率对其美国国内票房成绩进行了一番调整。扣除通胀因素后,在排在前十名的几部电影中,有几部电影的票房收入高得令人咂舌。特别要指出的是,本文所有票房数字均是基于2014年的美元币值计算而出,因为截止到上周末,联邦劳工统计局尚未发布2015年的通胀数据。
Having said that, Fortune presents a list of the highest-grossing animated movies of all time.
闲话少叙,请看《财富》为您奉献的史上最高票房收入动画电影排行榜。
10. Toy Story 2
《玩具总动员2》
The 1999 sequel to 1995's critically and commercially acclaimed Toy Story, this second installment finds Buzz Lightyear and the gang trying to rescue their pal Woody from the clutches of a remorseless toy dealer.
由于1995年推出的首部《玩具总动员》(Toy Story)叫好又叫座,制片方于1999年拍摄了该电影的续集。在本片中,巴斯光年和他的朋友们试图从一个冷酷的玩具商手中营救出他们的朋友胡迪。
While the first movie had won accolades from critics and audiences alike, the sequel was a huge step forward in terms of story and characterization, and raised the bar for what a children's movie could do. It took in $246 million as the 20th Century wrapped up, for a total of $350 million after inflation.
《玩具总动员1》获得了影评人和观众的一致赞誉,《玩具总动员2》则在历史和角色刻画上都向前迈了一大步,为以后的儿童电影树立了更高的标杆。该片出品方20世纪公司狂揽2.46亿美元,经通胀调整后约为3.5亿美元。
9. Shrek
《怪物史莱克》
In 2001, a hideous ogre with a Scottish accent voiced by Mike Meyers made his big-screen debut. Children everywhere were delighted, and the flagship effort in a highly profitable franchise was born.
2001年,一只由迈克•麦耶斯配音,操苏格兰口音的搞笑怪兽登上大银幕,并一下子征服了全球各地的小朋友。一个利润丰富的商业主题就此诞生。
Full of tongue-in-cheek references to other films, it kept mom and dad amused while junior reveled in the glorious fart humor. It raked in $268 million at the domestic box office, or $358 million today.
由于片中时常出现对其它电影的恶搞桥段,该片在吸引儿童的同时,也让陪同看片的父母们忍俊不禁。该片当时的美国票房为2.68亿美元,折合现在的3.58亿美元。
8. Shrek the Third
《怪物史莱克3》
By 2007, the Shrek franchise had already proven itself a highly profitable commodity, making a third trip back to the well mandatory. Featuring the voices of Monty Python alumni John Cleese and Eric Idle, as well as that of radio host Larry King as Doris the Ugly Stepsister, the third installment did even better than the original, with domestic box office receipts of $323 million, or $369 million today.
到2007年,史莱克早已成为一块金字招牌,其第三部电影也就顺理成章地上映了。除了电台主持人拉里•金为“丑陋的继姐”配音外,英国知名喜剧团体Monty Python成员约翰•克里斯和埃里克•爱都也为本片倾情献声。该片的反响甚至超过了第一部,美国国内票房收入达到3.23亿美元,折合现在的3.69亿美元。
7. Despicable Me 2
《卑鄙的我2》
Released in 2010, the original Despicable Me took in $252 million. Naturally, this meant that there had to be a sequel, which was delivered to salivating children in the summer of 2013.
2010年上映的《卑鄙的我》(Despicable Me )获得了2.52亿美元的票房成绩。如此佳绩当然意味着必然要拍续集。2013年夏天,《卑鄙的我2》终于火爆上映。
Adorable tykes across this great nation returned to the multiplexes to delight in the antics of Gru (Steve Carell) and the Minions, who could be seen gracing pajamas, cookies and other merchandise everywhere you looked. The movie earned $368 million, or $374 million in today’s dollars, and was also nominated for a Best Animated Feature Oscar. It lost, but the filmmakers could console themselves by crying into a pillow made of money.
全美的小朋友再次进入电影院,欣赏格鲁(由史蒂夫•卡莱尔配音)和小黄人们的滑稽搞笑。穿着背带裤的小黄人继续各种卖萌耍宝。该片获得3.68亿美元票房,折合现在的3.74亿美元。《卑鄙的我2》也被提名为当年的奥斯卡最佳动漫长片奖,虽然最后未能成功抱得奥斯卡小金人,但当制片方流下伤感的泪水时,他们至少可以抱着赚来的一大堆美金擦擦眼角。
6. Monsters, Inc.
《怪兽公司》
Monsters, Inc. is the story of two creatures that help power their hometown of Monstropolis with the screams of the children they scare. It features the voices of John Goodman, Billy Crystal and Steve Buscemi, and is the rare children’s film that parents could actually enjoy along with their kids.
《怪兽公司》(Monsters, Inc)讲述了在一个靠小孩子恐惧的尖叫声提供能源的怪兽世界里,两只小怪兽如何成为怪兽公司头牌恐吓者的故事。本片的配音演员有约翰•古德曼、比利•克里斯托和史蒂夫•布西密等,它也是少数父母可以与孩子共同享受观影乐趣的儿童片之一。
It opened to huge box office totals in November 2001, with only the first Harry Potter and Lord of the Ringsmovies able to knock it off its lofty perch. It earned $290 million in its theatrical run, or $388 million in today's dollars.
该片在2001年11月一经上映就获得巨额票房,当时只有《哈利波特》(Harry Potter )第一部和《指环王》(Lord of the Ring)系列电影能把它拉下票房榜首宝座。该片的票房收入达到2.9亿美元,约合现在的3.88亿美元。
5. Frozen
《冰雪奇缘》
If you are the parent of a girl under age 10 or so, then you do not need the plot of 2013's Frozen encapsulated for you. The musical fantasy, which raked in $400 million ($406 million today), is the subject of maniacal fandom, and your daughter – or maybe even your son – has probably been more than happy to talk your ear off about it since its release.
如果你有一个十岁以下的女儿,那你完全不必担心没看过《冰雪奇缘》(Frozen )。这部狂揽4亿美元(折合现在的4.06亿)的音乐幻想片是孩子们的狂热话题。自从这部片子上映以来,你的女儿,甚至你的儿子可能早已不厌其烦地向你描绘了多次片中的情节。
Frozen reached its box office total through repeat viewings, and it spawned sing-along events at theaters that became the kiddie equivalent of The Rocky Horror Picture Show. The plethora of Frozen-themed birthday parties and little girls dressed up as Princess Elsa at Halloween should be a big hint to parents that their children are not about to "let it go" any time soon.
《冰雪奇缘》不仅吸引了许多儿童反复观看,而且它还衍生了一批以此为主题的音乐剧,后者就相当于是孩子们的《洛基恐怖秀》。各地冒出的一大堆《冰雪奇缘》主题生日会,以及万圣节上无数扮演埃尔莎公主的小女孩,充分说明了“冰雪热”短时间内难以消退,父母们还是“随它吧”。
4. Toy Story 3
《玩具总动员3 》
Coming 11 years after Toy Story 2, moviegoers could have been forgiven for wondering what more the franchise could possibly have to say. However, critics and moviegoers alike were stunned to find that the third installment was in fact the best of the series, and it took in $415 million, the equivalent of $451 million today.
在《玩具总动员2》播出11年后,很多观影者可能好奇《玩具》系列是否还有进一步挖掘的空间。不过等《玩具3》上映后,观影者和影评人惊奇地发现,第三部其实是整个系列中水准最高的一部。该片获得了4.15亿美元的票房收入,约合今天的4.51亿美元。
Like Big Hero 6, it won the Academy Award for Best Animated Feature. Also like Big Hero 6, there may have been more than a few parents in the theater who did not expect it to be as tearful as it was. Despite the movie ending on a note that seemed to rule out another sequel, a fourth installment is currently scheduled for 2017.
像《超能陆战队》一样,该片也获得了奥斯卡最佳动画长片奖。另外很多父母没有想到,这部片子最后也像《超能陆战队》一样有泪点。尽管在片子末尾的彩蛋处表明制片方可能会再次推出续集,但目前看来,第四部《玩具总动员》可能要到2017年才会推出。
3. Finding Nemo
《海底总动员》
Finding Nemo is like Bambi, in that it belongs to the long, proud tradition of Disney films in which the main character's mother gets killed, thereby necessitating years of therapy for the little children who saw it.
和《小鹿斑比》(Bambi)一样,《海底总动员》(Finding Nemo)的故事情节也沿用了迪斯尼多年来屡试不爽的桥段:主角的母亲惨死后,目睹这一幕的孩子需要多年的心理建设才能恢复过来。
The story of a lost clownfish from the Great Barrier Reef, the 2003 film took in $380 million at the domestic box office, or $489 million after inflation. It was the highest-grossing G-rated film ever made until Toy Story 3conquered it with its unadjusted box office gross.
本片讲述了一只小丑鱼在大堡礁被抓走,小丑鱼的父亲为爱寻子的冒险历程。这部2003年的电影获得了3.8亿美元的国内票房,约合现在的4.89亿美元。在《玩具总动员3》上映之前,它一直是美国电影史上票房最高的G级片,直至前者凭借未经通胀调整的票房收入打破了它的纪录。
2. Shrek 2
《怪物史莱克2》
Shrek 2 was released in 2004 and followed the adventures of the unsightly ogre and his newly betrothed wife Fiona. It parodies such well-known children's stories as The Wizard of Oz and The Little Mermaid, and also introduced Puss in Boots, a swashbuckling Mexican cat voiced by Antonio Banderas.
《怪物史莱克2》上映于2004年,它继续讲述了史莱克与妻子费欧娜的冒险故事。片中也恶搞了《绿野仙踪》和《小美人鱼》等知名童话故事。同时本片还加入了一个新角色——由安东尼奥•班德拉斯配音的墨西哥“靴子猫”。
The most popular film in the entire franchise, it earned $441 million at the domestic box office, the equivalent of a staggering $553 million today. A fourth film, Shrek Forever After, was released in 2010, but the status of a much hinted-at fifth film remains shrouded in mystery.
作为《怪兽史莱克》系列中最受欢迎的一部,该片在美国获得了4.41亿美元的票房收入,约合现在的5.53亿美元。该系列的第四部也于2010年推出,但目前还不知道第五部的制作进展情况。
1. The Lion King
《狮子王》
It should come as no surprise that The Lion King is the highest-grossing animated film of all time. A stone cold classic beloved by children for over 20 years – and maybe a few of their parents too – the 1994 movie inspired three video games and a musical now in its 18th year on Broadway.
史上票房最高的动画电影被《狮子王》(The Lion King )摘得,应该是名至实归的,谁也不会感到意外。这部里程碑式的经典大片被孩子们深深热爱了20多年,当年最早的一批辛巴小粉丝如今也为人父母了。这部摄制于1994年的电影已经被改编成三种视频游戏和一部音乐剧,后者已经在百老汇上演了18年。
The movie's domestic box office take of $423 million is impressive even before it's adjusted for inflation, at which point it reaches a Titanic-esque $676 million. It leaves every other animated movie on this list in its dust, with the cruel and unrelenting force of a wildebeest stampede.
该片的票房收入高达4.23亿美元,即便不用通胀率进行调整,这个数额也是相当惊人了,而在用通胀率调整后,它的票房数字折合现在的6.76亿美元,达到了《泰坦尼克号》(Titanic)的高度,像非洲大草原上迁徙的角马一样,无情地将其它所有上榜电影甩在了它扬起的尘埃里。
Java nio的一个严重BUG,导致cpu 100% - 代码之美 - 博客频道 - CSDN.NET
这个BUG会在linux上导致cpu 100%,使得nio server/client不可用,具体的详情可以看这里http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933 。令人失望的是这个BUG直到jdk 6u4才解决,sun的拖沓让人难以相信。这个BUG在server端容易出现,因为server端有频繁地接入断开连接。
使用jdk 6u4之前版本的nio框架都有这个隐患,除非你的框架很好地处理了这个可能的隐患。Grizzly的处理方式比较简单,也就是BUG报告里面提到的方式,在SelectionKey.cancel()之后马上进行了一次select调用将fd从poll(epoll)中移除:
Java代码:
this.selectionKey.cancel();
try {
// cancel key,then select now to remove file descriptor
this.selector.selectNow();
} catch (IOException e) {
onException(e);
log.error("Selector selectNow fail", e);
}
实际上这样的解决方式还是留有隐患的,因为key的取消和这个selectNow操作很可能跟Selector.select操作并发地在进行,在两个操作之间仍然留有一个极小的时间窗口可能发生这个BUG。因此,你需要更安全地方式处理这个问题,jetty的处理方式是这样,连续的 select(timeout)操作没有阻塞并返回0,并且次数超过了一个指定阀值,那么就遍历整个key set,将key仍然有效并且interestOps等于0的所有key主动取消掉;如果在这次修正后,仍然继续出现select(timeout)不阻塞并且返回0的情况,那么就重新创建一个新的Selector,并将Old Selector的有效channel和对应的key转移到新的Selector上。
long before=now;
int selected=selector.select(wait);
now = System.currentTimeMillis();
_idleTimeout.setNow(now);
_timeout.setNow(now);
// Look for JVM bugs
// http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6403933
if (__JVMBUG_THRESHHOLD>0 && selected==0 && wait>__JVMBUG_THRESHHOLD && (now-before)<(wait/2) )
{
_jvmBug++;
if (_jvmBug>=(__JVMBUG_THRESHHOLD2))
{
synchronized (this)
{
_lastJVMBug=now;
// BLOODY SUN BUG !!! Try refreshing the entire selector.
final Selector new_selector = Selector.open();
for (SelectionKey k: selector.keys())
{
if (!k.isValid() || k.interestOps()==0)
continue;
final SelectableChannel channel = k.channel();
final Object attachment = k.attachment();
if (attachment==null)
addChange(channel);
else
addChange(channel,attachment);
}
_selector.close();
_selector=new_selector;
_jvmBug=0;
return;
}
}
else if (_jvmBug==__JVMBUG_THRESHHOLD || _jvmBug==__JVMBUG_THRESHHOLD1)
{
// Cancel keys with 0 interested ops
for (SelectionKey k: selector.keys())
{
if (k.isValid()&&k.interestOps()==0)
{
k.cancel();
}
}
return;
}
}
else
_jvmBug=0;
这个方案能比较好的在jdk 6u4之前的版本上解决这个BUG可能导致的问题。Mina和Netty没有看到有处理这个BUG的代码,如果我看错了,请留言告诉我。Yanf4j一直采用的是grizzly的方式,准备加上jetty的处理方案。当然,最简单的方案就是升级你的JDK。
俺实际上被这个BUG害的很惨, 因为降到了jdk 6u4 CPU仍然会时不时的增高, 原因是低版本的Jetty同样在这方面处理的不是很合理.
Jetty关于这个BUG的描述:http://jira.codehaus.org/browse/JETTY-937, 用JETTY做为应用, JETTY1.6.22 + JDK 6U4俺现在测下来, CPU基本正常.
另外nio还有几个严重的bug,在实际运行中碰到了,sun在u18才修复,而现在u18还没正式发布。
http://download.java.net/jdk6/6u18/promoted/b01/changes/JDK6u18.b01.list.html
例如:http://bugs.sun.com/view_bug.do?bug_id=6693490
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6670302 这个BUG跟我这里描述的相似,解决的方法也是一样。
http://bugs.sun.com/view_bug.do?bug_id=6693490 这个BUG,一个间接影响也是关闭的channel一直有ready事件,select不阻塞并立即返回0,也就是导致CPU 100%,同样也是可以通过这里描述的方案解决的。
参考:
http://www.infoq.com/cn/articles/practice-of-java-nio-communication-framework
How To: Make Sure /etc/resolv.conf Never Get Updated By DHCP Client
Option # 3: Configure dhclient.conf
/etc/dhclient.conf or /etc/dhcp/dhclient.conf file contains configuration information for dhclient. You can turn on or off DNS update and other options for specific interface or all interface using this file. The man pages for DHCLIENT.CONF and DHCP-OPTIONS point out that in dhclient.conf, you should add this:
supersede domain-name-servers 202.54.1.2, 199.2.3.4;
OR
prepend domain-name-servers 1.2.3.4, 1.2.3.5;
Here is a sample config for you:
timeout 60; retry 60; reboot 10; select-timeout 5; initial-interval 2; reject 192.33.137.209; interface "eth0" { send host-name "laptop-area51.nixcraft.net.in.home"; send dhcp-client-identifier 00:30:48:33:BC:32; send dhcp-lease-time 3600; supersede domain-search "net.in.home", "cyberciti.biz", "vpx.nixcraft.net.in"; prepend domain-name-servers 8.8.8.8, 127.0.0.1; request subnet-mask, broadcast-address, time-offset, routers, domain-search, domain-name, domain-name-servers, host-name; require subnet-mask, domain-name-servers; }
Parent: Internet and Networking
The default setup of Ubuntu does not make it easy to use static DNS servers while using DHCP. If you use the standard ubuntu way of networking (ifupdown), you can edit /etc/network/interfaces
In that file you find the entry for your interface. If your interface is eth0, then look for the following lines:
auto eth0 iface eth0 inet dhcp
Add one line, so it looks like:
auto eth0 iface eth0 inet dhcp dns-nameservers ip.address.of.nameserver
Run
sudo invoke-rc.d networking restart
To make the changes effective
If you do not use ifupdown, you need to edit /etc/dhcp3/dhclient.conf
Find the lines
#prepend domain-name-servers 127.0.0.1; request subnet-mask, broadcast-address, time-offset, routers, domain-name, domain-name-servers, host-name, netbios-name-servers, netbios-scope;
And change them to
prepend domain-name-servers 1.2.3.4, 1.2.3.5; request subnet-mask, broadcast-address, time-offset, routers, domain-name, host-name, netbios-name-servers, netbios-scope;
Replace 1.2.3.4 and 1.2.3.5 with the addresses of your DNS servers.
Run
sudo invoke-rc.d networking restart
To make the changes effective:
netty/MemcacheClient.java at master · netty/netty · GitHub
/* | |
* Copyright 2014 The Netty Project | |
* | |
* The Netty Project licenses this file to you under the Apache License, | |
* version 2.0 (the "License"); you may not use this file except in compliance | |
* with the License. You may obtain a copy of the License at: | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | |
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | |
* License for the specific language governing permissions and limitations | |
* under the License. | |
*/ | |
package io.netty.example.memcache.binary; | |
import io.netty.bootstrap.Bootstrap; | |
import io.netty.channel.Channel; | |
import io.netty.channel.ChannelFuture; | |
import io.netty.channel.ChannelInitializer; | |
import io.netty.channel.ChannelPipeline; | |
import io.netty.channel.EventLoopGroup; | |
import io.netty.channel.nio.NioEventLoopGroup; | |
import io.netty.channel.socket.SocketChannel; | |
import io.netty.channel.socket.nio.NioSocketChannel; | |
import io.netty.handler.codec.memcache.binary.BinaryMemcacheClientCodec; | |
import io.netty.handler.codec.memcache.binary.BinaryMemcacheObjectAggregator; | |
import io.netty.handler.ssl.SslContext; | |
import io.netty.handler.ssl.SslContextBuilder; | |
import io.netty.handler.ssl.util.InsecureTrustManagerFactory; | |
import java.io.BufferedReader; | |
import java.io.InputStreamReader; | |
/** | |
* Simple memcache client that demonstrates get and set commands against a memcache server. | |
*/ | |
public final class MemcacheClient { | |
static final boolean SSL = System.getProperty("ssl") != null; | |
static final String HOST = System.getProperty("host", "127.0.0.1"); | |
static final int PORT = Integer.parseInt(System.getProperty("port", "11211")); | |
public static void main(String[] args) throws Exception { | |
// Configure SSL. | |
final SslContext sslCtx; | |
if (SSL) { | |
sslCtx = SslContextBuilder.forClient() | |
.trustManager(InsecureTrustManagerFactory.INSTANCE).build(); | |
} else { | |
sslCtx = null; | |
} | |
EventLoopGroup group = new NioEventLoopGroup(); | |
try { | |
Bootstrap b = new Bootstrap(); | |
b.group(group) | |
.channel(NioSocketChannel.class) | |
.handler(new ChannelInitializer<SocketChannel>() { | |
@Override | |
protected void initChannel(SocketChannel ch) throws Exception { | |
ChannelPipeline p = ch.pipeline(); | |
if (sslCtx != null) { | |
p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT)); | |
} | |
p.addLast(new BinaryMemcacheClientCodec()); | |
p.addLast(new BinaryMemcacheObjectAggregator(Integer.MAX_VALUE)); | |
p.addLast(new MemcacheClientHandler()); | |
} | |
}); | |
// Start the connection attempt. | |
Channel ch = b.connect(HOST, PORT).sync().channel(); | |
// Read commands from the stdin. | |
System.out.println("Enter commands (quit to end)"); | |
System.out.println("get <key>"); | |
System.out.println("set <key> <value>"); | |
ChannelFuture lastWriteFuture = null; | |
BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); | |
for (;;) { | |
String line = in.readLine(); | |
if (line == null) { | |
break; | |
} | |
if ("quit".equals(line.toLowerCase())) { | |
ch.close().sync(); | |
break; | |
} | |
// Sends the received line to the server. | |
lastWriteFuture = ch.writeAndFlush(line); | |
} | |
// Wait until all messages are flushed before closing the channel. | |
if (lastWriteFuture != null) { | |
lastWriteFuture.sync(); | |
} | |
} finally { | |
group.shutdownGracefully(); | |
} | |
} | |
} |
(8)刘良华家庭教育100条建议_教育现象学_新浪博客
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
使用Mahout基于用户和物品相似度进行协同过滤推荐内容
基于用户User协同过滤
package mahout;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.apache.mahout.cf.taste.common.TasteException;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.CachingRecommender;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.model.JDBCDataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
/**
* 基于用户相似度进行推荐
* mahout基于协同过滤(CF)的推荐
* 用户对物品进行评分,对于无评分只有喜欢、不喜欢的,可以将喜欢置为5分,不喜欢置为1分
* @author itindex
*
*/
public class Mahout {
public static void main(String[] args) throws TasteException, IOException {
//(1)----连接数据库部分
// MysqlDataSource dataSource = new MysqlDataSource();
// dataSource.setServerName("localhost");
// dataSource.setUser("admin");
// dataSource.setPassword("admin");
// dataSource.setDatabaseName("mahoutDB");
// //(2)----使用MySQLJDBCDataModel数据源读取MySQL里的数据
// JDBCDataModel dataModel = new MySQLJDBCDataModel(dataSource, "table1", "userId", "itemId", "preference", "date");
//(3)----数据模型部分
//把MySQLJDBCDataModel对象赋值给DataModel
// DataModel model = dataModel;
DataModel model = new FileDataModel(new File("D:/intro.csv"));
//用户相似度UserSimilarity:包含相似性度量和邻居参数
UserSimilarity similarity = new PearsonCorrelationSimilarity(model);
//相邻用户UserNeighborhood
UserNeighborhood neighborhood = new NearestNUserNeighborhood(2, similarity, model);
//一旦确定相邻用户,一个普通的user-based推荐器被构建,构建一个GenericUserBasedRecommender推荐器需要数据源DataModel,用户相似性UserSimilarity,相邻用户相似度UserNeighborhood
Recommender recommender = new CachingRecommender(new GenericUserBasedRecommender(model, neighborhood, similarity));
//向用户1推荐2个商品
List<RecommendedItem> recommendations = recommender.recommend(1, 2);
for(RecommendedItem recommendation : recommendations){
//输出推荐结果
System.out.println(recommendation);
}
}
}
基于物品Item进行协同过滤:
package mahout;
import java.io.File;
import java.util.Collection;
import java.util.List;
import org.apache.mahout.cf.taste.impl.model.file.FileDataModel;
import org.apache.mahout.cf.taste.impl.recommender.CachingRecommender;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.GenericItemSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
/**
* 基于Item 物品相似度进行推荐
* 用户对物品进行评分,对于无评分只有喜欢、不喜欢的,可以将喜欢置为5分,不喜欢置为1分
* @author itindex
*
*/
public class RecommenderIntro {
public static void main(String[] args) throws Exception {
//装载数据文件,实现存储,并为计算提供所需的所有偏好,用户和物品数据
DataModel model = new FileDataModel(new File("D:/intro.csv"));
//基于物品的推荐
Recommender recommender1 ;
ItemSimilarity otherSimilarity = new EuclideanDistanceSimilarity(model);
GenericItemSimilarity similarity2 = new GenericItemSimilarity(otherSimilarity, model);
recommender1 = new CachingRecommender(new GenericItemBasedRecommender(model, similarity2));
//为用户1推荐一件物品1,1
List<RecommendedItem> recommendedItems = recommender1.recommend(1, 2);
//输出
for (RecommendedItem item : recommendedItems) {
System.out.println(item);
System.out.println(item.getItemID());
System.out.println(item.getValue());
}
}
}
intro.csv文件格式:
用户id,物品id,评分
1,10,5
1,12,5
1,14,1
2,12,5
3,10,5
3,12,5
3,13,5
3,14,1
4,10,5