Ubuntu下部署FastDFS 5.05

  很早前得知这样一个开源分布式的文件存储方案,一直没有正式的使用过,正好这次相册升级可以试试了,起初以为fastdfs也是通过block来优化小文件存储的,实际上也是文件形式管理,可以预见大量的小文件还是会有问题,可能更好的解决方案是淘宝TFS。不过fastdfs已远远满足我的需求了。而且及其轻量,这货在google code上早已停止更新,最新的版本可以在这里获取,目前下载的最新版本是5.05,更新于2014-12-02。在这里可以找到更多的说明。

  下载好后,server端分为两个部分,一个是tracker,一个是storage。顾名思义,前者调度管理,负载均衡,后者则是实际的存储节点。两个都能做成集群,以防止单点故障。以前的4.x版本依赖libevent,现在不需要了,只需要libfastcommon。安装方法如下:

1. 下载安装libfastcommon

git clone https://github.com/happyfish100/libfastcommon.git
cd libfastcommon/
./make.sh
./make.sh install

确认make没有错误后,执行安装,64位系统默认会复制到/usr/lib64下。

这时候需要设置环境变量或者创建软链接

export LD_LIBRARY_PATH=/usr/lib64/
ln -s /usr/lib64/libfastcommon.so /usr/local/lib/libfastcommon.so

2. 下载安装fastdfs

tar xzf FastDFS.tar.gz
cd FastDFS/
./make.sh
./make.sh install

确认make没有错误后,执行安装,默认会安装到/usr/bin中,并在/etc/fdfs中添加三个配置文件。

3. 修改配置文件
首先将三个文件的名字去掉sample,暂时只修改以下几点,先让fastdfs跑起来,其余参数调优的时候再考虑。
tracker.conf 中修改

base_path=/usr/fastdfs #用于存放日志。

storage.conf 中修改

base_path=/usr/fastdfs-storaged #用于存放日志。
store_path0=/usr/fastdfs0 #存放数据,若不设置默认为前面那个。
tracker_server=192.168.29.132:22122 #指定tracker服务器地址。

client.conf 中同样要修改

base_path=/usr/fastdfs #用于存放日志。
tracker_server=192.168.29.132:22122 #指定tracker服务器地址。

4. 启动tracker和storage

/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf

5. 检查进程

root@ubuntu:~# ps -ef |grep fdfs
root       7819      1  0 15:24 ?        00:00:00 /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf
root       8046      1  0 15:36 ?        00:00:01 fdfs_storaged /etc/fdfs/storage.conf start

表示启动ok了,若有错误,可以在/usr/fastdfs目录下检查日志。

6. 上传/删除测试
使用自带的fdfs_test来测试,使用格式如下:

root@ubuntu:~# fdfs_test /etc/fdfs/client.conf upload /home/steven/01.jpg 
...
group_name=group1, ip_addr=192.168.29.132, port=23000
storage_upload_by_filename
group_name=group1, remote_filename=M00/00/00/wKgdhFTV0ZmAP3AZAPk-Io7D4w8580.jpg
...
example file url: http://192.168.29.132/group1/M00/00/00/wKgdhFTV0ZmAP3AZAPk-Io7D4w8580.jpg
storage_upload_slave_by_filename
group_name=group1, remote_filename=M00/00/00/wKgdhFTV0ZmAP3AZAPk-Io7D4w8580_big.jpg
...
example file url: http://192.168.29.132/group1/M00/00/00/wKgdhFTV0ZmAP3AZAPk-Io7D4w8580_big.jpg

使用fdfs_delete_file来删除文件,格式如下:

fdfs_delete_file /etc/fdfs/client.conf group1/M00/00/00/wKgdhFTV11uAXgKWAPk-Io7D4w8667.jpg

可以看到,上传ok了,这里会生成两个文件,这是fastdfs的主/从文件特性,以后再介绍。example file url是不能在浏览器中直接打开的,除非配合nginx使用,这里我不需要了。删除文件需要完整的group_name和remote_filename。

Ubuntu下编译和部署Hadoop 2.2

  在Ubuntu下编译各种项目总会遇到不少的问题,尤其是缺少各种依赖,好友都推荐用CentOS。不过个人对Ubuntu这个品牌以及背后的Canonical公司比较喜欢,加之用过其桌面版多年,算是熟悉了。这里记录下编译和部署Hadoop 2.2的一些过程,以供快速参考。

0、虚拟机环境准备
  宿主机器配置i7 8g内存,我这里用VMware虚拟了4台Ubuntu Server 64bit,每台机器分配1g内存。主机名分别为h0,h1,h2,h3,配置好每台机器的/etc/hosts,将各主机名映射到私有ip。

127.0.0.1       localhost
192.168.10.33   h0
192.168.10.176  h1
192.168.10.207  h2
192.168.10.90   h3

  配置免密码ssh登录,这里只将h0作为namenode和secondarynamenode,h1~3作为datanode,应此只需要配置h0到h1~3的免密码登录,以及各虚拟机自己的免密码登录。

ssh-keygen -t rsa
cat id_rsa.pub >> authorized_keys
scp authorized_keys ubuntu@h1:~/.ssh/authorized_keys_from_h0
scp authorized_keys ubuntu@h2:~/.ssh/authorized_keys_from_h0
scp authorized_keys ubuntu@h3:~/.ssh/authorized_keys_from_h0

1、安装编译环境
  由于Hadoop官方提供的只有32位环境,所以需要自己编译64位的,以下步骤仅在h0上操作。首先准备编译需要的组件,这里随系统决定所需。当然Java运行环境也是必须的,apt-get安装OpenJDK即可。

sudo apt-get install subversion maven cmake libssl-dev

2、签出Hadoop 2.2源代码

svn checkout http://svn.apache.org/repos/asf/hadoop/common/tags/release-2.2.0/

3、添加jetty-util依赖
  编辑vim hadoop-common-project/hadoop-auth/pom.xml,添加:

<dependency>
   <groupId>org.mortbay.jetty</groupId>
   <artifactId>jetty-util</artifactId>
   <scope>test</scope>
</dependency>

4、编译安装protobuf 2.5

wget https://protobuf.googlecode.com/files/protobuf-2.5.0.tar.bz2
tar jxvf protobuf-2.5.0.tar.bz2
cd protobuf-2.5.0/
./configure
make
sudo make install

添加环境变量,或者重启一次

export LD_LIBRARY_PATH=/usr/local/lib/

5、执行编译
首次执行:

mvn package -Pdist,native -DskipTests -Dtar

如果有错误,根据错误原因处理,一般都是缺少依赖。装好后重复执行即可,也可以添加-e -X参数,打印更多的日志来帮助查找错误。成功后可以看到以下的输出:

[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 46:40.307s
[INFO] Finished at: Fri Jan 17 17:32:23 CST 2014
[INFO] Final Memory: 66M/188M
[INFO] ------------------------------------------------------------------------

6、安装配置
  建立以下文件夹:

~/hadoop/dfs/data
~/hadoop/dfs/name
~/hadoop/temp

  编译好的Hadoop可以在release-2.2.0/hadoop-dist/target/hadoop-2.2.0/找到,我这里将其复制到~/hadoop下,切换到目录:

cd ~/hadoop/hadoop-2.2.0/etc/hadoop/

配置以下几个文件,如果没有的,可以在复制改名对应的template。

hadoop-env.sh
修改JAVA_HOME 为系统Java Home环境,apt-get安装的OpenJDK一般是这个路径。

export JAVA_HOME=/usr/lib/jvm/default-java

core-site.xml
ubuntu为运行Hadoop的用户。

<configuration>
     <property>
          <name>fs.defaultFS</name>
          <value>hdfs://h0:9000</value>
     </property>
     <property>
          <name>io.file.buffer.size</name>
          <value>131072</value>
     </property>
     <property>
          <name>hadoop.tmp.dir</name>
          <value>file:/home/ubuntu/hadoop/temp</value>
          <description>Abase for other temporary directories.</description>
     </property>
     <property>
          <name>hadoop.proxyuser.ubuntu.hosts</name>
          <value>*</value>
     </property>
     <property>
          <name>hadoop.proxyuser.ubuntu.groups</name>
          <value>*</value>
     </property>
</configuration>

hdfs-site.xml

<configuration>
     <property>
          <name>dfs.namenode.secondary.http-address</name>
          <value>h0:9001</value>
     </property>
     <property>
          <name>dfs.namenode.name.dir</name>
          <value>file:/home/ubuntu/hadoop/dfs/name</value>
     </property>
     <property>
          <name>dfs.datanode.data.dir</name>
          <value>file:/home/ubuntu/hadoop/dfs/data</value>
     </property>
     <property>
          <name>dfs.replication</name>
          <value>3</value>
     </property>
     <property>
          <name>dfs.webhdfs.enabled</name>
          <value>true</value>
     </property>
</configuration>

mapred-site.xml

<configuration>
     <property>
          <name>dfs.namenode.secondary.http-address</name>
          <value>h0:9001</value>
     </property>
     <property>
          <name>dfs.namenode.name.dir</name>
          <value>file:/home/ubuntu/hadoop/dfs/name</value>
     </property>
     <property>
          <name>dfs.datanode.data.dir</name>
          <value>file:/home/ubuntu/hadoop/dfs/data</value>
     </property>
     <property>
          <name>dfs.replication</name>
          <value>3</value>
     </property>
     <property>
          <name>dfs.webhdfs.enabled</name>
          <value>true</value>
     </property>
</configuration>

yarn-site.xml

<configuration>
     <property>
          <name>yarn.nodemanager.aux-services</name>
          <value>mapreduce_shuffle</value>
     </property>
     <property>
          <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
          <value>org.apache.hadoop.mapred.ShuffleHandler</value>
     </property>
     <property>
          <name>yarn.resourcemanager.address</name>
          <value>h0:8032</value>
     </property>
     <property>
          <name>yarn.resourcemanager.scheduler.address</name>
          <value>h0:8030</value>
     </property>
     <property>
          <name>yarn.resourcemanager.resource-tracker.address</name>
          <value>h0:8031</value>
     </property>
     <property>
          <name>yarn.resourcemanager.admin.address</name>
          <value>h0:8033</value>
     </property>
     <property>
          <name>yarn.resourcemanager.webapp.address</name>
          <value>h0:8088</value>
     </property>
</configuration>

slaves
定义节点的主机名:

h1
h2
h3

  至此,配置就算完成了,将Hadoop目录复制到另外三台机器上,放相同的目录下。

scp -r hadoop-2.2.0/ h1:~/hadoop/
scp -r hadoop-2.2.0/ h2:~/hadoop/
scp -r hadoop-2.2.0/ h3:~/hadoop/

7、启动Hadoop

在h0上执行:

./sbin/start-dfs.sh
./sbin/start-yarn.sh

  用jps可以查看Java进程所对应的服务。

ubuntu@h0:~/hadoop/hadoop-2.2.0$ jps
1902 NameNode
1604 SecondaryNameNode
2076 ResourceManager

ubuntu@h1:~$ jps
1354 DataNode
1123 NodeManager

ubuntu@h2:~$ jps
1146 DataNode
1378 NodeManager

ubuntu@h3:~$ jps
1139 DataNode
1371 NodeManager

  到此,namenode和datanode都启动完毕。

ngrok 微信接口开发利器

  由于开发微信公众号项目,经常需要将本地部署的接口让外网能直接调用到,偶然发现还有个叫ngrok的神器专门做了这件事,不但提供了一个在外网能够安全的访问内网Web主机,还能捕获所有请求的http内容,方便调试,甚至还支持tcp层端口映射。支持Mac OS X,Linux,Windows平台。

1. ngrok下载运行

  体积很小,官网下载后直接解压得到一个二进制文件,在shell中执行./ngrok 80即可,默认会分配随机的二级域名来访问,转发到本机的80端口。可以通过-help参数来查看详细的说明,运行后如下提示:

Tunnel Status                 online
Version                       1.6/1.5
Forwarding                    http://steven-mbp.ngrok.com -> 127.0.0.1:8080
Forwarding                    https://steven-mbp.ngrok.com -> 127.0.0.1:8080
Web Interface                 127.0.0.1:4040
# Conn                        16
Avg Conn Time                 558ms

  我这里是使用了自定义二级域名,意味着访问http://steven-mbp.ngrok.com就如同访问内网的http://127.0.0.1:8080,很方便吧。通过ngrok提供的管理界面(127.0.0.1:4040)可以清楚的看到当前有哪些连接,以及请求的url,可以进行replay。

2. ngrok常用示例

1. 采用自定义二级域名steven-mbp.ngrok.com转发到本机的8080端口。

./ngrok -subdomain steven-mbp 8080

2. tcp端口转发,当然外网端口是随机分配的。

./ngrok -proto=tcp 22

3. 转发到局域网其他的机器

./ngrok 192.168.0.1:80

4. 绑定顶级域名(付费才可用),在dashboard中添加域名,将域名cname解析到ngrok.com即可。

./ngrok -hostname test.dorole.com 8080

3. ngrok配置文件

  ngrok可以将参数写到文件中,默认是放在~/.ngrok。例如:

tunnels:
  client:
    auth: "user:password"
    proto:
      https: 8080
  ssh:
    proto: 
      tcp: 22
  test.dorole.com
    proto:
      http: 9090

  这里定义了三个隧道,client表示转发http到本机8080,同时要求验证,ssh表示支持远程访问,第三个是绑定了域名转发到9090。这时候只需要一个./ngrok start client ssh test.dorole.com即可快速启动这三个隧道服务。

  每一个隧道的配置节点都有五个参数,proto,subdomain,auth,hostname和remote_port,每个隧道必须有proto参数来指定本地地址和端口。auth参数用于在http(s)中身份认证,而remote_port用于在tcp隧道中指定远程服务器端口。如果没有配置subdomain参数,ngrok会默认一个二级域名与隧道节点一样的名字。

4. 配置文件中的其他参数

authtoken: abc123
inspect_addr: "0.0.0.0:8888"
tunnels:
  ...

  authtoken用于设置登录ngrok的授权码,可以在ngrok首页的dashboard中查看到。inspect_addr用于设置监听ip,比如设置为0.0.0.0:8080意味着监听本机所有ip的8080端口上。ngrok也支持自己架设ngrokd服务器,在配置中通过server_addr: “dorole.com:8081″来指定自己搭建的服务器地址。设置trust_host_root_certs: true来支持TLS加密协议的证书信任。

  官网:https://ngrok.com/

编译Open-JDK-7详细记录

  本次编译的系统环境是Ubuntu Linux 64-bit,编译用户root。需要以下软件包的依赖,如果是新的环境直接复制粘贴到终端即可,如果系统有了也不会重复安装的,建议安装之前把软件仓库update一次。

apt-get install mercurial build-essential gawk m4 openjdk-6-jdk ant 
libasound2-dev libcups2-dev libxrender-dev xutils-dev binutils libmotif3 
libmotif-dev zip libfreetype6-dev xorg-dev x11proto-print-dev

1、下载OpenJDK的源代码

hg clone http://hg.openjdk.java.net/jdk7u/jdk7u-dev
cd jdk7u-dev/
chmod 755 get_source.sh
./get_source.sh

2、设置环境变量

#语言选项
export LANG=C

#bootstrap jdk路径
export ALT_BOOTDIR=/usr/lib/jvm/java-6-openjdk-amd64

#允许自动下载依赖
export ALLOW_DOWNLOADS=true

#并行编译的线程数,按CPU核数配置就可以了,我这机器是i7 8核
export HOTSPOT_BUILD_JOBS=8
export ALT_PARALLEL_COMPILE_JOBS=8

#与之前编译的版本做比较,没意义,跳过即可
export SKIP_COMPARE_IMAGES=true

#使用预编译的头文件,不加慢些
export USE_PRECOMPILED_HEADER=true

#要编译的内容,这里只编译了JDK和LANGTOOLS。
export BUILD_LANGTOOLS=true
export BUILD_JDK=true

#不需要打包
export BUILD_DEPLOY=false
export BUILD_INSTALL=false

#设置编译输出的目录
export ALT_OUTPUTDIR=/root/jdk7u-bin

#取消系统java环境变量
unset JAVA_HOME
unset CLASSPATH

  这里要求系统先装一个JDK环境,编译OpenJDK7至少要求OpenJDK6以上,因为编译期间有很多java语言写的过程,这个叫做“Bootstrap JDK”,我这是用apt-get安装的,所以默认路径如此。更多配置信息可以参考源代码目录下的README-builds.html。

3、编译

  用env确认下变量没错的话就可以进行编译了,如果有错误,依据错误提示修正后用make clean清理一次,再执行编译。

make 2>&1 | tee $ALT_OUTPUTDIR/build.log

  这样可以记录下编译的日志,不需要也可以直接make all,我这里编译大概需要15分钟就可以了,看到以下信息表示成功。

#-- Build times ----------
Target all_product_build
Start 2013-12-24 13:04:19
End   2013-12-24 13:21:02
00:01:41 corba
00:04:18 hotspot
00:00:16 jaxp
00:00:19 jaxws
00:09:34 jdk
00:00:32 langtools
00:16:43 TOTAL

4、运行检测

  进入之前配置的输出目录下的bin,执行java -version可以看到build里面加入了用户机器名

root@dorole.com:~/jdk7u-bin/bin# ./java -version
openjdk version "1.7.0-internal"
OpenJDK Runtime Environment (build 1.7.0-internal-stevenyang_2013_12_24_13_04-b00)
OpenJDK 64-Bit Server VM (build 24.60-b04, mixed mode)

  Java的编译和解释就算ok了,接下来还要测试下jvm是否正常。进入jdk7u-bin/hotspot/outputdir目录,可以发现有子目录linux_amd64_compiler2/,前面的linux是根据宿主系统来决定的,我们这里是linux,amd64不用多说,compiler2表示Server VM,compiler1表示Client VM。进入后又有子目录分别对应了不同的优化级别,优化级别越高,性能越牛叉,生成的代码越难以调式,具体哪个目录下有内容得看make的参数,我这里是在product/下面。

  虚拟机的启动器名字叫gamma,先编辑目录下的env.sh,可以看到默认的JAVA_HOME并不是我们自己编译的,修改下即可。可以执行目录下的test_gamma脚本来进行测试,这个脚本主要是调用javac去编译jdk7u-dev/hotspot/make/test/Queens.java,并执行解八皇后问题。

  直接执行gamma可能会失败,因为找不到新编译出来的libjvm.so文件,没关系加入到系统就好了。在/etc/ld.so.conf.d中建立java.conf,内容为libjvm.so所在目录。再执行ldconfig即可。

root@dorole.com:/etc/ld.so.conf.d# cat java.conf
/root/jdk7u-bin/hotspot/outputdir/linux_amd64_compiler2/product

root@dorole.com:/etc/ld.so.conf.d# ldconfig
root@dorole.com:/etc/ld.so.conf.d# ldconfig -p | grep jvm
        libjvm.so (libc6,x86-64) => /root/jdk7u-bin/hotspot/outputdir/linux_amd64_compiler2/product/libjvm.so

  看到有最后一行的输出就可以了,再回到gamma目录,执行就可以了。

root@dorole.com:~/jdk7u-bin/hotspot/outputdir/linux_amd64_compiler2/product# ./gamma -version
Using java runtime at: /root/jdk7u-bin
openjdk version "1.7.0-internal"
OpenJDK Runtime Environment (build 1.7.0-internal-stevenyang_2013_12_24_13_04-b00)
OpenJDK 64-Bit Server VM (build 24.60-b04, mixed mode)

  到此,整个编译OpenJDK就算完成了。

尝试 Arch Linux

1. 前言

  折腾了多年的Ubuntu Linux,一直是依赖于图形界面,刚买vps那会儿居然连deb安装包都忘了该用什么命令了。试用过许多Linux的发行版,数Ubuntu用的时间最长,优点还是蛮多的:

  1. 中文支持比较完善
  2. 软件仓库丰富
  3. 驱动齐全
  4. 优雅的主题

  等等。当然缺陷也不少,相对openSUSE和Fedora,稳定性较差,系统臃肿,etc目录文件混乱,不易整理。

  喜欢简洁点的,Arch就是个不错的选择,安装镜像才340M,默认不带图形界面。更多可参考官网,下载地址:http://www.archlinux.org/download/

2. 使用U盘安装

  想想以前几乎每个Ubuntu新版本发布都是刻DVD,太不环保了。即使有了DVD-RAM还是得花不少时间来刻,所以这次选择U盘安装。上次在amazon标错价16g金士顿u盘才卖66元,幸运的捡了一个。在Linux中可以使用dd将ISO直接复制到U盘并制作成可引导的系统盘,命令如下:

sudo dd if=*.iso of=/dev/sdb bs=4M

/dev/sdb 为U盘所在的设备

  这样处理后的U盘,在windows系统中将无法使用,需要在磁盘管理器中再次格式化即可恢复。用U盘引导后直接进入安装,安装方法屏幕都有提示。需要注意的是在Arch中推荐将/boot单独作为一个分区,大小100m即可,在Ubuntu中则很随意。关于交换分区,我指定了一个分区为swap格式就无法格式化,删除后忽略即可通过。

接下来是选择软件包,这里最好将base和base-devel都选中,后面很多东西都是要编译安装的。mbr信息可以写在/dev/sda上。其中在安装grub的时候会打开编辑器编辑grub配置,如果有windows系统记得在这里取消最后几行注释,很简单。

3. 安装网卡驱动

  大概几分钟的样子,就装完了。重启后就直接到了shell环境了,登录后发现没有网卡驱动,这可是最重要的一个硬件,这个不装好后面的都白搭。我acer笔记本是broadcom的网卡,其具体型号可以用lspci命令看到,我的是Netlink 57780,找一台能上网的或者手机到broadcom官网下载驱动,地址:http://www.broadcom.com/support/ethernet_nic/downloaddrivers.php

  全部解压后只需make && make install,再重启即可完成网卡驱动的安装,具体可参考tg3-3.116j.tar.gz中的readme.txt。

  折腾到此暂告一段落,离正真使用还差很远,有时间再来整图形界面。