Canon 6D WiFi 初体验

  话说用了三年的尼康早已折腾的不成样了,早早出掉后换到佳能门下,正好上周和朋友出去拍了些片子,发现 WiFi 这个功能还是很实用的,于是有了这个 WiFi 体验报告。佳能从13年开始新出的机型基本都开始带 WiFi 功能了,像 6D,70D 等,WiFi 主要有6大功能:

  1. 相机间互传图片
  2. 连接到智能手机
  3. WiFi 打印
  4. EOS Utility 遥控
  5. 发送至网络服务
  6. DLAN 播放

相机间互传

  这个比较简单,只要支持 WiFi 的佳能相机应该都可以,但不能发送 RAW 格式,由于没有多台机器,也无法测试速度了,不过 6D 的 WiFi 是支持 802.11n 的,网络瓶颈应该不大。

连接到智能手机

  这个是比较常用的,手机端要安装 EOS Remote,这里有两个模式可用,在户外没有 WiFi 热点的时候,6D 可以用“相机接入点”模式来创建一个热点,用手机接入,再用 App 来配对即可传输图片或者遥控控制。传输图片 RAW 会转成 JPG 格式,尺寸缩小到 S2。如果在室内有 WiFi 路由器的时候,可以将相机和手机都接入到同一个局域网,更加方便。在 App 上可以实时查看屏幕取景,光圈、快门、对焦、ISO全部可以手动,相当于有了旋转屏加快门线。拍摄夜景长曝光或者合照的时候非常好用,缺点是比较耗电,尤其是手机耗电快。

  这里必须吐槽下,由于这个功能用的 WiFi 并非直连技术,效率不太理想,操作步骤也非常麻烦。从创建热点到手机搜寻到热点、接入、获取 IP、App 配对识别,都要消耗好几秒的时间。好还相机上为每种接入都提供了三个保存记录,只需要设置一次便可方便启动。希望未来能做到像 Apple 的 AirDrop 一样,能快速发现,并脱离网络独立运作。

WiFi打印

  这个倒不算新鲜词了,早起很多卡片机都支持这个功能,需要打印机支持 PictBridge (DPS over IP)即可。

EOS Utility 遥控

  PC 上安装 EOS Utility 就可以通过 WiFi 控制相机拍摄了,和传统的 USB 连接没什么区别,有些比较高级的设置可以在这里配上,比如添加镜头矫正数据,自定义风格以及短片配音。

发送至网络服务

  这个功能比较鸡肋,更奇葩的是压根就没对中国开放,不过本着折腾的心还是激活玩了一把,想要体验的话必须要下载非大陆版的EOS Utility,我是在佳能美国官网下载的,安装后会提示去Canon CIG(CANON iMAGE GATEWAY)注册一个账号,这时候连接上相机可以进入 Web 设置服务,登录后可以授权关联 Twitter,FaceBook,Flickr 等社交账号,保存后,在相机上就可以点击对应的图标进入分享了,这里要确保相机接入的 WiFi 是可以正常上网的。

  说到这里,可以发现,完全可以利用连接到手机导出图片再上传到社交平台来代替这个功能,当然也不是完全没区别的,手机只能传输缩小的图片,而这个是可以发送 JPG 原图,在 CIG 是可以下载到原图的。大概是我们这户外的免费热点少之又少,所以觉得很鸡肋。

DLAN播放

  这里就没有设备测试了,不过可以想象得到和插入 HDMI 连接到电视机效果是差不多的啦。而且之前在树莓派上架设 DLAN 服务的时候体验糟糕透了,不抱希望。

总结

  总的来说这个功能还是很好玩的,使得照片的分享传播更具有实时性。我一般的拍摄习惯是 RAW 格式导入到 Aperture 中,再稍稍调整下,导出成较高品质的 JPG 存档,再和朋友分享,这样一下来可能都好几周的时间了。说到这里其实应该和市面上销售的 WiFi SD卡来做一番比较,不过这种卡也没打算用过,记得有一款传 RAW 到 PC 上还要升级到最高级的套餐才行,太无耻了,想必这个市场也会被慢慢淘汰掉的。

IMG_0327

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/

  介于ngrok的局限性和高度依赖,我用Java重新写了一个转发项目:御花园(https://ifport.com/),欢迎注册使用,目前免费提供,后续资源不足会考虑收费方案。

2013 小结

  第三年,觉得这一年过的太快了,事情也多了起来,年底了也小结一下。

  工作上一个跟了三年的亲子项目,基本进入了暂停阶段,不再投入研发,仅维持现有客户关系。这一点可以说是比较遗憾的。三年前亲子项目正式立项,作为公司中期战略规划。组建团队在这个行业从零开始探索,先后也有过几次重心转移。我记得最初重心是放在手机终端上,因为当时公司在手机终端市场还有一定的资源,那时我们主要是做了一个后台以提供数据为主。后来转为以Web网站为主,主打移动亲子园这样一个产品概念,同时推出了亲子资讯、新闻,App站。紧接着做了订课通这样一个里程碑的产品,线上卖课程。这时期产品团队也在不断的扩大,先后有了自己的产品、原画、设计、研发和测试。具备了完整的软件开发管理体系。线上卖课程听起来很不错,但实际上是个卖方市场,我们能拿到的优惠并不多,所以做了没多久重心转为线上线下结合,线下做活动,做品牌,做服务,这一时期我们研发团队也做了内部用的OA系统,这一阶段开始就意味着淡出互联网了。当然任何项目都不会是一帆风顺的,其中原因也难以直接下结论,总之也算是有始有终了。当然也说不定在14年的行业旺季也还有转机呢。

  自考,可能今年花时间第二多的就在这个上面了,1月、4月、7月、10月,每逢考试月就忙得不行,考前抱佛脚还是很奏效的,没挂过科,希望以后也不挂科。基本上考完了一大半了,没什么太大压力,深大计算机信息管理专业,预计今年第四季度可以搞定。

  驾考,我记得报名时间正好是12年年底最后一天,因为再过一天就大幅度涨价了,在13年上半年考完科目一整整一年没再练过车。驾校那边一直说是人太多,排队轮候着。前几个月联系说是12月安排下,看来又是黄了,不过这事在我这也是优先级最低了,先放着,不急。考虑到三年的有效期,还是在今年催下尽快搞定算了。

  数码,这一年里先后把iPad,23寸显示器,Acer笔记本,单反,镜头全卖了,一来是可以收回点现金用于更新换代,二来租的房东西多了以后搬家麻烦,还是现金能带来安全感啊。今年买入的最大一笔Macbook Pro,漂亮,好用,速度快,太喜欢了。

  学习,前段时间面了一些公司,离期望还是略有不足,同时也不想再做重复性的事情,三年来虽收获了实战经验,却忘光了基础知识。趁这段时间不忙,回过头来重新啃书,最近在看的有《Java 编程思想》,《深入了解Java 虚拟机》,《Java 虚拟机规范》。用同事的一句话说,当你的才华不足以支撑你的野心,那么你该学习了。

  电影,之前混迹的PT站陆续倒闭了,这一年几乎没怎么下电影,但印象中还有一部好电影值得推荐,那就是《Intouchables》法国电影,虽然是老片子了,不过在上半年看过之后还是留下了深刻印象,逢人必提。

  音乐,收听音乐的习惯发生了大的变化,很少再去找专辑下载,而改为在线听了。以前用的比较多的是Foobar2000,现在改为以虾米音乐为主。同时在iTunes上订阅了些Podcast,上下班路上听。在听的有NPR的《Wait Wait Don’t Tell Me!》和《TED Radio Hour》,BBC的《Global News》和《CNN Radio News》,技术类的《Teahour.fm》,情感类的《清清下午茶》。

  游戏,Mac系统上也基本没有什么游戏可玩。手机端倒是有个好游戏《Clash of Clans 部落战争》战争策略类,目前9本,67级,玩这种游戏好处是可以慢慢玩,不用时时刻刻盯着,不耽误时间。

  摄影,这一年按快门的次数比12年少了很多,主要是周边的风景都看腻了,又懒得出远门,就连活动也很少参加了。仅在11月份约Lisa在深大拍了一组校园人像,冬季的阳光最适合拍人像了,清新温暖又惬意。其余的就当是散步随拍了。这一年用手机拍照较多了,发在Instagram的照片也比微博多了,而微博基本哑巴了,当然写博客是永远不会减的。很庆幸能有这样一个兴趣爱好,为之学习,进步。风景拍漂亮了,人拍更美了,这个世界还是很美好的。

  运动,基本上以散步和爬山为主,器械锻炼减少了。常去的两个地方:深圳湾和南山,每周必选其一。深圳湾主要在红树林站出发,走到体育公园,正好10公里路,一般步行两个小时到两个半小时,出发时间一般是选择半晚样子。南山一般是在南门别墅登山口上,横过整片南山到荔林公园下山,耗时也是两个半小时左右。基本上都会叫上老同学Steve同行,无所不聊。

  2013差不多就这样了,继续努力~~

Java 内存区域分析

  Java虚拟机在执行的过程中会将物理内存划分为几个区域来进行管理,这些区域都有特定用途和生命周期。Java虚拟机规范中提到,有以下6个部分组成:

1:寄存器(PC Register)

  Java虚拟机的多线程是通过轮流切换分配处理器执行时间来实现的,在任何一个时间点上,一个处理器只能执行一个线程中的指令,其余线程中断状态。因此为了记录每个线程当前所执行的指令,每个线程都会拥有一个独立的PC寄存器,用于保存线程执行状态。而且寄存器互不影响,类似这样的内存空间也叫做“线程私有”内存。

  特别的,如果执行的方法是native方法,寄存器是不确定的(undefined),如果是Java方法,寄存器保存的是当前字节码指令地址。PC寄存器的容量至少应当能保存一个 returnAddress 类型的数据或者一个与平台相关的本地指针的值。所以在计算内存使用的时候,这一部分可以忽略不计。

2:虚拟机栈(Java Virtual Machine Stacks)

  虚拟机栈也是线程私有的,与线程生命周期一致,创建的时候分配,终止的时候回收。在内存中以帧的形式存储,用于保存线程的局部变量表,局部计算结果,一个方法开始执行到返回结果,对于栈来说就是一个帧入栈和出栈的过程。其中局部变量表中包含了基本数据类型和引用对象(对象地址指针,字节码地址等等)

  在Java虚拟机规范第一版中,Java虚拟机栈也被直接称作Java栈,这个规范允许要么以固定尺寸来分配空间或者能动态扩展。如果栈大小是固定的,创建栈的时候,每一个Java虚拟机栈大小都可以独立选定。即通过参数决定栈大小或者最大最小值,内存可不要求连续。Java虚拟机的栈可以分配于更底层语言中的堆中。

  Java虚拟机栈上操作会有两个异常需要考虑,一是线程计算请求的栈深度(容量)超过虚拟机所允许的深度,将抛出StackOverflowError异常,如果虚拟机可以动态扩展,并试图扩展,但内存不足了,或者没有足够内存创建新线程的时候,将抛出OutOfMemoryError异常。

3:堆(Heap)

  堆是可供所有线程共享的区域,类实例和数组分配的区域。启动虚拟机的时候创建,堆中存储的对象受自动内存管理(GC),所以无需手动释放。空间分配也可以是固定大小或动态扩展,内存可不要求连续,这点和栈是一样的。如果需求的堆容量超过了自动内存管理能提供的最大容量,也会抛出OutOfMemoryError异常。

4:方法区(Method Area)

  方法区同样是线程共享的区域,有点类似于传统语言的“Text Segment”区。存储了类结构,例如:运行时常量池,字段和方法数据,以及构造函数和普通方法的字节码内容。还包括一些类,实例,接口初始化时用到的特殊方法。特殊方法例如init等等。

  方法区同样在虚拟机启动的时候创建,尽管方法区是堆的逻辑组成中的一部分,不过这个区可以实现垃圾回收,也可以不实现,规范不做强制要求,代码编译管理策略和物理内存分配都不做要求,具体得看虚拟机的实现了。

  当然,如果申请不到足够的内存,也会抛OutOfMemoryError。

5:运行时常量池(Run-Time Constant Pool)

  顾名思义,是每一个类或接口常量表现形式,包括若干种常量:从编译期可知的值到解析运行才知道的值。每一个常量池都保存在方法区中,在类被加载到虚拟机后创建出来。显然,构造常量池不能超过方法区大小,否则抛OutOfMemoryError。

6:本地方法栈(Native Method Stacks)

  这块区域是为Java调用非Java编写的代码而开辟的空间,实际上就是一块传统语言用到的栈。如果虚拟机不支持native方法,自身也不依赖传统栈,可以不分配本地方法栈空间,如果支持,一般都在线程创建的时候分配空间。本地方法栈的大小调整和前面几个一致。分配的栈容量不得超出本地方法栈最大容量,否则抛StackOverflowError异常,无法申请足够的内存扩展栈的话,将抛出OutOfMemoryError异常。

  官方参考:link