基于GridFS构建分布式文件系统
首先看看什么是GridFS:
GridFS is a mechanism for storing large binary files in MongoDB. There are several
reasons why you might consider using GridFS for file storage:
• Using GridFS can simplify your stack. If you’re already using MongoDB, GridFS
obviates the need for a separate file storage architecture.
• GridFS will leverage any existing replication or autosharding that you’ve set up for
MongoDB, so getting failover and scale-out for file storage is easy.
• GridFS can alleviate some of the issues that certain filesystems can exhibit when
being used to store user uploads. For example, GridFS does not have issues with
storing large numbers of files in the same directory.
• You can get great disk locality with GridFS, because MongoDB allocates data files
in 2GB chunks.
上面这段话摘自《MongoDB权威指南》
到现在为止你大概知道GridFS能为我们做点什么了,简单点就是可以帮我们存储文件。那么如何将文件存储到GridFS中呢?
你确保已经安装了MongoDB,如何安装配置请参考《MongoDB权威指南》APPENDIX A 部分,这里就不多说了。
下面以java为例子,看看如何实现。下载mongo-java-driver驱动包。
File uploadfile = new File("C://Users/bdjb0201/Desktop/default.jpg"); //待上传的文件
DB db = mongoTemplate.getDb();//获得db
GridFS gridFS = new GridFS(db, "FSimgs");
GridFSInputFile file;
try {
file = gridFS.createFile(uploadfile);
file.setFilename(uploadfile.getName());
file.save();//保存
//下面用来查询
List<GridFSDBFile> list = gridFS.find(uploadfile.getName());
for (GridFSDBFile gridFSDBFile : list) {
System.out.println(gridFSDBFile.getUploadDate());//输出上传时间
}
} catch (IOException e) {
e.printStackTrace();
}
上面的短短几行代码就实现了文件的上传,以及查看功能。
看起来很方便,但是在大多数的应用中,应用服务器只负责处理动态请求,静态资源一般由专门的web服务器去处理(apache、nginx等)。
那么很多情况就像下面图中描述的一样:
现在应用服务器将文件写入到MongoDB中已经完成,接下来就是如何让web服务器(图中NG)可以直接访问那个被存入GridFS的文件就可以 了。在github上有个项目nginx-gridfs就是干这个事情的,项目首页(https://github.com/mdirolf /nginx-gridfs),上面详细讲解了如何安装配置nginx-gridfs。
下面是我的安装笔记:
//确保你已经安装了mongodb和git工具
// 下载nginx-gridfs
cd/opt
git clonegit://github.com/mdirolf/nginx-gridfs.git
cdnginx-gridfs
gitsubmodule init
gitsubmodule update
//安装 nginx
tar -zxvfnginx-xxx.tar.gz
cdnginx-xxx
./configure--add-module=/opt/nginx-gridfs/
make
make install
注【/opt/nginx-gridfs/ 为nginx-gridfs下载目录】
//配置nginx
在nginx.conf中server加入:
location /gridfs/ {
gridfs my_app field=filename type=string;
}
注【my_app 为mongodb存储文件的数据库名字】
//启用nginx
//打开浏览器输入要访问的图片:http://192.168.1.109:28118/gridfs/6b6e567cjw1dmea3323e1j.jpg。 你看到了之前上传的文件
***************************一下是下载jar包的实战**********************
Mongodb GridFS图片文件存储解决方案
之前解决方案是接收图片数据后,将图片直接存储到盘阵,然后通过Apache做服务器,将图片信息存储到数据库,并且存储一个Apache的访问路径。
目前需要后台服务存储图片,将图片存储到MongoDB集群中,然后通过Nginx中的nginx-gridfs模块进行访问,在浏览器中通过url访问,效果与Apache访问本地文件一样。
一、安装MongoDB(参照:Linux 安装mongoDB 2.2.7http://my.oschina.net/MrMichael/blog/266501)
二、安装nginx-gridfs
(1)下载nginx-gridfs插件
网上有传出使用git安装此插件的,这个比较麻烦,我在文章的附件中留了下载包。本人测试可用。
下载后还要下载mongo的c语言驱动包,这个也可以在附件中下载。
下载完成后进行解压:tar -zxf nginx-gridfs.tar.gz
tar -zxf mongo-c-driver-0.94.2.tar.gz
[root@bdjb-0197 opt]# tar -zxf nginx-gridfs.tar.gz
[root@bdjb-0197 opt]# tar -zxf mongo-c-driver-0.94.2.tar.gz
解压完成后将驱动包内容全部拷贝到nginx-gridfs目录下的mongo-c-driver目录中:
[root@bdjb-0197 opt]# mv mongo-c-driver-0.94.2/* nginx-gridfs/mongo-c-driver/
如果有提示已经存在src目录,没有关系,忽略。然后就是下载Nginx,编译安装的过程了。
mv:是否覆盖"nginx-gridfs/mongo-c-driver/src"? y
mv: 无法将"mongo-c-driver-0.94.2/src" 移动至"nginx-gridfs/mongo-c-driver/src": 目录非空
三、安装NGinx
有人说:“Nginx版本太高对支持nginx-gridfs模块不是很成功,使用的Nginx1.7弄了一天都出不来图片。换成1.0.1就好了。”但是我用的是1.5.1是可以的。
下载:nginx-1.5.1.tar.gz 和 pcre-8.32.tar.gz
1 . 安装 pcre 让nginx支持rewrite
pcre-8.32.tar.gz上传到/opt 目录下面
1) 解压 pcre
tar -zxf pcre-8.32.tar.gz//解压 pcre 后 /opt下面会有 pcre-8.32 文件夹
2)配置pcre
cd /opt/pcre-8.32
3)make
./configure
#./configure
#make
命令后屏幕会生成一堆文件,不用去管它
4)安装
在linux 中输入
make install
2.安装 nginx
nginx-1.5.1.tar.gz上传到/opt 目录下面
1) 解压 nginx
tar zxvf nginx-1.5.1.tar.gz 解压 nginx 后 /opt 下面会有nginx-1.5.1 文件夹
2 配置nginx
cd nginx-1.5.1
> ./configure --prefix=/usr/local/nginx --with-openssl=/usr/include/openssl --with-http_stub_status_module --add-module=/opt/nginx-gridfs
./configure --prefix=/usr/local/nginx --with-http_stub_status_module
3)make
在linux 中输入 make 命令后屏幕会生成一堆文件,不用去管它
4)安装 make install
在linux 中输入 make install
5) 检查是否安装成功
>cd /usr/local/nginx/sbin
>./nginx -t
可能出错:sbin/nginx: error while loading shared libraries: libpcre.so.1: cannot open shared object file: No such file or directory
解决方法(直接运行):
32位系统 [root@sever lib]# ln -s /usr/local/lib/libpcre.so.1 /lib
64位系统 [root@sever lib]# ln -s /usr/local/lib/libpcre.so.1 /lib64
然后执行ps -ef | grep nginx 查看nginx进程确认是否真的已经启动了,在进程列表里会有最起码两个, worker(nginx工作进程)和master(nginx主进程)
root 4349 1 0 02:24 ? 00:00:00 nginx: master process sbin/nginx -c conf/nginx.conf
nginx 4350 4349 0 02:24 ? 00:00:00 nginx: worker process
root 4356 28335 0 02:30 pts/1 00:00:00 grep nginx
NGINX 就 OK了
6)启动nginx
cd /usr/local/nginx/sbin 目录下面 输入
./nginx //启动 nginx
7 )检查是否启动成功
ie 浏览器中输入 http://192.168.15.132
出现nginx 欢迎界面说明启动成功
说明:nginx 默认配置端口是80.配置文件主要是conf 文件夹中的nginx.conf 文件
8)停止nginx
pkill -9 nginx
四、配置GridFS+NGinx
配置mogon-gridfs地址:
在vim /usr/local/nginx/conf/nginx.conf配置文件中,增加下面的内容:
location /pics/ {
gridfs rms
field=filename
type=string;
mongo 127.0.0.1:27017;
}
gridfs:nginx识别插件的名字
rms:数据库名称
[root_collection]: 选择collection,如root_collection=blog, mongod就会去找blog.files与blog.chunks两个块,默认是fs
[field]:查询字段,保证mongdb里有这个字段名,支持_id, filename, 可省略, 默认是_id
[type]:解释field的数据类型,支持objectid, int, string, 可省略, 默认是int
[user]:用户名, 可省略
[pass]:密码, 可省略
mongo:mongodb url mongo名称 地址:端口
具体shell如:
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
location /pics/ {
gridfs rms
field=filename
type=string;
mongo 127.0.0.1:27017;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
启动:/usr/local/nginx/sbin/nginx
查看日志:tail -f /usr/local/nginx/logs/error.log
四、测试开发
测试例子使用java开发,代码在附件中
(1)图片写入
全部的例子在附件中,GridFSTest.rar,例子还需要mongodb的驱动jar包mongo-java-driver-2.9.3.jar 。
try {
Mongo mongo = new Mongo("192.168.100.52", 27017);// 创建连接
DB db = mongo.getDB("pics"); // 选择数据库
byte[] files = createImage(800, 600, "800 X 600"); // 创建图片
save(files, "test3.jpg", db); // 存储图片
} catch (Exception e) {
e.printStackTrace();
}
(2)文件获取
通过代码获取图片就不写了。只写如何在程序中传递文件路径,然后在前端展示。
存储图片信息时,可以加上ip地址:http://192.168.1.237/pics/default.jpg ,然后前端应用通过给定的URL地址就可以获取图片内容了。
在浏览器中输入地址可以获得相同的效果。
*********************************************NGinx启动、停止***************************************
启动操作:
命令:
nginx -c /usr/nginx/conf/nginx.conf
-c参数指定了要加载的nginx配置文件路径。
停止操作:
停止操作是通过向nginx进程发送信号(什么是信号请参阅linux文章)来进行的
步骤1:查询nginx主进程号
ps -ef | grep nginx
在进程列表里面找master进程,它的编号就是主进程号了。
步骤2:发送信号
从容停止Nginx:
kill -QUIT 主进程号
快速停止Nginx:
kill -TERM 主进程号
强制停止Nginx:
pkill -9 nginx
另外,若在nginx.conf配置了pid文件存放路径则该文件存放的就是Nginx主进程号,如果没指定则放在nginx的logs目录下。有了pid文件,我们就不用先查询Nginx的主进程号,而直接向Nginx发送信号了,命令如下:
kill -信号类型 '/usr/nginx/logs/nginx.pid'
平滑重启
如果更改了配置就要重启Nginx,要先关闭Nginx再打开?不是的,可以向Nginx发送信号,平滑重启。
平滑重启命令:
kill -HUP 住进称号或进程号文件路径
注意,修改了配置文件后最好先检查一下修改过的配置文件是否正确,以免重启后Nginx出现错误影响服务器稳定运行。判断Nginx配置是否正确命令如下:
nginx -t -c /usr/nginx/conf/nginx.conf
平滑升级
如果服务器正在运行的Nginx要进行升级、添加或删除模块时,我们需要停掉服务器并做相应修改,这样服务器就要在一段时间内停止服务,Nginx可以在不停机的情况下进行各种升级动作而不影响服务器运行。
步骤1:
如果升级Nginx程序,先用新程序替换旧程序文件,编译安装的话新程序直接编译到Nginx安装目录中。
步骤2:执行命令
kill -USR2 旧版程序的主进程号或进程文件名
此时旧的Nginx主进程将会把自己的进程文件改名为.oldbin,然后执行新版Nginx。新旧Nginx会同市运行,共同处理请求。
这时要逐步停止旧版Nginx,输入命令:
kill -WINCH 旧版主进程号
慢慢旧的工作进程就都会随着任务执行完毕而退出,新版的Nginx的工作进程会逐渐取代旧版工作进程。
此时,我们可以决定使用新版还是恢复到旧版。
不重载配置启动新/旧工作进程
kill -HUP 旧/新版主进程号
从容关闭旧/新进程
kill -QUIT 旧/新主进程号
如果此时报错,提示还有进程没有结束就用下面命令先关闭旧/新工作进程,再关闭主进程号:
kill -TERM 旧/新工作进程号
这样下来,如果要恢复到旧版本,只需要上面的几个步骤都是操作新版主进程号,如果要用新版本就上面的几个步骤都操作旧版主进程号就行了。
上面就是Nginx的一些基本的操作,希望以后Nginx能有更好的方法来处理这些操作,最好是Nginx的命令而不是向Nginx进程发送系统信号
来源:oschina
链接:https://my.oschina.net/u/1473715/blog/282400