一、问题的原因分析
(1)在进行磁盘格式化时,没有正确指定inode的上限值,100T的硬盘,INODE的个数=26226048,即2200W个,文件数太少,建议扩大10倍以上,这样做势必会造成INODE的存储空间变大,约100G左右,但对于100T的磁盘来讲,不算什么。事实已经这样,无法动态调整INODE值,只能是重新格式化时指定-N参数。
(2)因为赤峰老师大量上传的是OFFICE文件,云平台对于OFFICE的预览采用的是OFFICE365的在线预览方式,但此地还在继续生成SWF文件,虽然生成也没用。1个OFFICE文件根据页数的不等,可能生成的SWF文件个数从10到几百不等,小文件太多,占用了太多的INODE值。
二、暂时处理办法
(1)将Preview下小的文件(小于5MB)的移动到一个临时增加的4T硬盘上,这块硬盘的INODE值=301989888,看到的吧?触目惊心,4T硬盘的INDOE值是100T的15倍!!!
(2)配置nginx.conf,将静态文件请求分别到两个地方检查,实在没有再走云存储。
location ~ /down/Preview/ { root /usr/local/tomcat7/webapps/; set $cba ""; set $abc "0"; set $oss_endpoint "http://video.edusoa.com"; if (!-e $request_filename) { #set $abc "1"; root /data/tomcat7/webapps/; } if (!-e $request_filename) { set $abc "1"; } if ($abc = "1") { rewrite_by_lua ' ...
(3)效果如下图:
测试用例:http://ypt.cfedu.net/dsideal_yy/html/down/Preview/00/0010A914-0FE4-8179-7CD4-89867B91F7A3_10.swf
(4)在没有进行长远的根治办法之前,定期执行下面的命令,以解燃眉之急
# 执行小文件搬家程序 cd /usr/local/huanghai nohup ./MoveSmallFile & 查看 [root@localhost huanghai]# ps -ef | grep MoveSmallFile root 42917 41820 0 07:32 pts/3 00:00:00 ./MoveSmallFile root 42965 41820 0 07:33 pts/3 00:00:00 grep MoveSmallFile
三、长远的办法
(1)停止生成SWF文件。
(2)用100TB的硬盘挂载上,重新格式化,设定好INODE值,所有文件迁移到新硬盘上,旧硬盘格式化后重新设置INODE值。
(3)将文件重新迁移回旧硬盘,回收新硬盘。
四、附小文件搬家程序源码,供参考和修改:(go语言版本)
package main import ( "bufio" "fmt" "io" "io/ioutil" "log" "os" ) func CopyFile(srcFilePath string, dstFilePath string) (written int64, err error) { srcFile, err := os.Open(srcFilePath) if err != nil { fmt.Printf("打开源文件错误,错误信息=%v ", err) } defer srcFile.Close() reader := bufio.NewReader(srcFile) dstFile, err := os.OpenFile(dstFilePath, os.O_WRONLY|os.O_CREATE, 0777) if err != nil { fmt.Printf("打开目标文件错误,错误信息=%v ", err) return } writer := bufio.NewWriter(dstFile) defer dstFile.Close() return io.Copy(writer, reader) } func PathExists(path string) (bool, error) { _, err := os.Stat(path) if err == nil { return true, nil } if os.IsNotExist(err) { return false, nil } return false, err } //工作目录 var WorkingPath = "/usr/local/tomcat7/webapps/dsideal_yy/html/down/Preview/" //创建目录 var createDir = "/data/tomcat7/webapps/dsideal_yy/html/down/Preview/" func main() { //拼接二级子目录 var subPathArray []string charArray := "0123456789ABCDEF" l := len(charArray) for i := 0; i < l; i++ { first := charArray[i : i+1] for j := 0; j < l; j++ { second := charArray[j : j+1] subPathArray = append(subPathArray, first+second) } } for i := 0; i < len(subPathArray); i++ { os.MkdirAll(createDir+subPathArray[i], os.ModePerm) fmt.Println("创建目录成功:", subPathArray[i]) } //遍历所有子目录下文件 for i := 0; i < len(subPathArray); i++ { current := WorkingPath + subPathArray[i] fmt.Println("当前检查的目录:" + current) files, errDir := ioutil.ReadDir(current) if errDir != nil { log.Fatal(errDir) return } //输出所有文件 for _, file := range files { if file.Size() < 1024*1024*1024*5 { //拷贝走 sourceFile := current + "/" + file.Name() targetFile := createDir + subPathArray[i] + "/" + file.Name() //先删除 exist, _ := PathExists(targetFile) if exist { fmt.Println("发现文件存在,先删除之:" + targetFile) //存在则先删除之 err := os.Remove(targetFile) if err != nil { // 删除失败 fmt.Println("文件删除失败:" + targetFile) } else { // 删除成功 fmt.Println("文件删除成功:" + targetFile) } } _, err := CopyFile(sourceFile, targetFile) if err != nil { fmt.Println(" 文件写入失败,是不是磁盘满了?") return } fmt.Println(current+"/"+file.Name()+",size=", file.Size()) //删除旧的 err = os.Remove(sourceFile) if err != nil { // 删除失败 fmt.Println("原始文件删除失败:" + sourceFile) } else { // 删除成功 fmt.Println("原始文件删除成功:" + sourceFile) } } } } }