2019年3月,伯克利的一篇论文《A Berkeley View on Serveless Computing》,预测了Serverless对未来10年云计算的影响;
2019年12月,AWS REInvent上发布了诸多Serverless相关的更新,反响热烈。
Serverless无疑已经成为学术界和工业界关注的焦点。
本文主要聊聊个人对Serverless的一些理解。
EST.
2013
2019年3月,伯克利的一篇论文《A Berkeley View on Serveless Computing》,预测了Serverless对未来10年云计算的影响;
2019年12月,AWS REInvent上发布了诸多Serverless相关的更新,反响热烈。
Serverless无疑已经成为学术界和工业界关注的焦点。
本文主要聊聊个人对Serverless的一些理解。
本书的作者是香奈儿前CEO莫琳·希凯,书名《深度思考》,副标题 - 不断逼近问题的本质。

这是一本关于提升逻辑思维能力的大作,也是有效提高写作和演讲水平的红宝书,
趁这几天宅在家里,前细后粗的读了一遍。(后面的太啰嗦,选择性放弃)
几乎所有的应用程序都需要配置(实例的配置信息,外部系统的访问信息等),而这些配置显然不应该被打包到应用程序本身中。
本篇文章看看如何在Kubernetes中配置应用程序的信息。
命令行 最简单的应用配置方式,是使用命令行。
配置文件
随着配置信息增多,考虑到维护成本,可以将配置信息存储到配置文件中。但对于容器而言,使用配置文件的方式需要将配置项打包到镜像中,而且每次配置信息的变更都会导致重新生成镜像,重新部署,维护和变更成本较高。
在容器应用中,使用环境变量来实现配置,也是较普遍的一种做法,通过将参数传递给容器中的应用,变更容器运行期的配置信息,如MySQL官方的镜像就使用环境变量MYSQL_ROOT_PASSWORD 来修改超级用户root的密码。
另外,基于volume的方式获取配置信息也是一种可行的方式,如使用Git Repo存储配置信息,能有效的做到版本化管理会随时回退。
在K8S中,存储配置信息的资源被称ConfigMap,本部分将介绍ConfigMap、Secret的使用。
在Docker容器中,通常使用如下方式传递参数:
ENTRYPOINT定义可执行命令CMD传递参数在ENTRYPOINT中,可以使用如下两种方式启动应用:
ENTRYPOINT node app.jsENTRYPOINT ["node", "app.js"]注意: 这两种方式的区别在于前者是先启动Shell,由Shell调用node,而后者直接启动node应用。
在K8S中,可以通过配置文件中的command和args来设置容器中的ENTRYPOINT和CMD
譬如
kind: Pod
spec:
containers:
- image: some/image
command: ["/bin/command"]
args: ["arg1", "arg2", "arg3"]
它们之间的区别如下图所示:
| Docker | Kubernetes | 描述 |
|---|---|---|
| ENTRYPOINT | command | 在容器中执行命令 |
| CMD | args | 给命令传递参数 |
在K8S中,使用env设置镜像中定义的环境变量。
譬如,容器中存在如下脚本,其中的INTERVAL使用环境变量进行设置:
#!/bin/bash
while :
do
echo $(date)
sleep $INTERVAL
done
在K8S中,其配置文件类似如下:
kind: Pod
spec:
containers:
- image: xxxxx
env:
- name: INTERVAL
value: "30"
...
Kubernetes允许将配置项分离到一个称为ConfigMap的单独对象中,它包含若干键/值对,并且值的范围可以从文本到整个配置文件。
之前我们了解了如何打包,作为Pod中的容器运行,使用临时或者永久存储机制,设置配置项,接下来我们探讨如何部署和升级。
假定在K8S中存在这样的应用:
初始情况,运行V1版本的应用。接下来,我们希望生成V2版本的镜像,并使用V2版本的Pod/容器进行升级。 存在两种方式:
一次新增全部数量,多次新增,每次部分数量)对于第一种方式:简单,但是存在部署的停机时间
对于第二种方式:系统需要同时处理两个版本的应用,尤其是数据Schema需要兼容新旧两个版本
本篇文章主要介绍在K8S中,pod的容器如何访问外部磁盘存储,以及容器间如何实现共享存储,主要内容包括
在非k8s世界中,管理员可以通过在配置文件中指定IP地址或主机名,容许客户端访问,但在k8s中这种方式是行不通的。因为Pod 是有生命周期的,它们可以被创建或销毁。虽然通过 ReplicationController 能够动态地创建Pod,但当Pod被分配到某个节点时,K8s都会为其分配一个IP地址,而该IP地址不总是稳定可依赖的。因此,在 Kubernetes 集群中,如果一组 Pod(称为 backend)为其它 Pod (称为 frontend)提供服务,那么那些 frontend 该如何发现,并连接到这组backend的Pod呢?
Kubernetes中内建了很多controller(控制器),这些相当于一个状态机,用来控制Pod的具体状态和行为。
Pod是kubernetes中你可以创建和部署的最小也是最简的单位。Pod代表着集群中运行的进程。Pod中封装着应用的容器(1或多个容器)、存储、独立的网络IP,并管理着容器运行的策略选项。
K8s的网络介绍
为了管理异构和不同配置的主机,为了便于Pod的运维管理,Kubernetes中提供了很多集群管理的配置和管理功能,通过namespace划分的空间,通过为node节点创建label和taint用于pod的调度等。
Kubernetes主要由以下几个核心组件组成:
Paxos发明人Leslie Lamport提出,分布式系统有两类特性:
保证系统的稳定,保证系统不会崩溃,不会出现业务错误,不会做坏事,是严格约束的。
使得系统可以提供功能,提高性能,增加易用性,让系统可以在用户“看到的时间内”做些好事,是尽力而为的。
从Kubernetes的系统架构和设计来看,存在两个最核心的设计理念,符合Lamport的理论:
容错性实际是保证Kubernetes系统稳定性和安全性的基础
易扩展性是保证对变更友好,可以快速迭代增加新功能的基础
[如需转载,请联系本人]
过去的几个月,我作为独立咨询师,为多个传统企业提供了微服务架构的培训、咨询以及交付工作。实际上,传统企业在过去多年的业务积累中,由于组织架构、业务发展和市场竞争等综合因素,技术体系相对封闭,缺乏快速交付的理念。因此,微服务的出现,加之社区的热捧,导致很多传统的团队过于追热而并没有完全理解微服务。
经过2015年的快速普及,微服务的优势被越来越多的传统组织和企业所认可,但由于架构相关的知识本身比较抽象,虽然各大会议上有很多互联网公司的案例分享,但开发者似乎依然很难全面了解微服务架构。
所以,希望通过本系列的文章以及视频,以一个真实的案例为背景,以持续交付和DevOps为主线,帮助初学者理解微服务架构,并能通过动手实验,了解相关的实践以及方法论。
精彩课程已经出炉,请移步这里
[如需转载,请联系本人]
过去的几个月,我作为独立咨询师,为多个传统企业提供了微服务架构的培训、咨询以及交付工作。实际上,传统企业在过去多年的业务积累中,由于组织架构、业务发展和市场竞争等综合因素,技术体系相对封闭,缺乏快速交付的理念。因此,微服务的出现,加之社区的热捧,导致很多传统的团队过于追热而并没有完全理解微服务。
经过2015年的快速普及,微服务的优势被越来越多的传统组织和企业所认可,但由于架构相关的知识本身比较抽象,虽然各大会议上有很多互联网公司的案例分享,但开发者似乎依然很难全面了解微服务架构。
所以,希望通过本系列的文章以及视频,以一个真实的案例为背景,以持续交付和DevOps为主线,帮助初学者理解微服务架构,并能通过动手实验,了解相关的实践以及方法论。
精彩课程已经出炉,请移步这里
[如需转载,请联系本人]
过去的几个月,我作为独立咨询师,为多个传统企业提供了微服务架构的培训、咨询以及交付工作。实际上,传统企业在过去多年的业务积累中,由于组织架构、业务发展和市场竞争等综合因素,技术体系相对封闭,缺乏快速交付的理念。因此,微服务的出现,加之社区的热捧,导致很多传统的团队过于追热而并没有完全理解微服务。
经过2015年的快速普及,微服务的优势被越来越多的传统组织和企业所认可,但由于架构相关的知识本身比较抽象,虽然各大会议上有很多互联网公司的案例分享,但开发者似乎依然很难全面了解微服务架构。
所以,希望通过本系列的文章以及视频,以一个真实的案例为背景,以持续交付和DevOps为主线,帮助初学者理解微服务架构,并能通过动手实验,了解相关的实践以及方法论。
精彩课程已经出炉,请移步这里
[如需转载,请联系本人]
过去的几个月,我作为独立咨询师,为多个传统企业提供了微服务架构的培训、咨询以及交付工作。在这些企业中,大部分的开发者对微服务的理解,以“银弹观念”为主。实际上,传统企业在过去多年的业务积累中,由于组织架构、业务发展和市场竞争等综合因素,技术体系相对封闭,缺乏快速交付的理念。因此,微服务的出现,加之社区的热捧,导致这种现象出现也是比较能理解的。
经过2015年的快速普及,微服务的优势被越来越多的传统组织和企业所认可,但由于架构相关的知识本身比较抽象,虽然各大会议上有很多互联网公司的案例分享,但开发者似乎依然很难全面了解微服务架构。
所以,希望通过本系列的文章,以一个模拟的案例为背景,以持续交付和DevOps为主线,帮助初学者理解微服务架构,并能通过动手实验,了解相关的实践以及方法论。
精彩课程已经出炉,请移步这里
[如需转载,请联系本人]
过去的几个月,我作为独立咨询师,为多个传统企业提供了微服务架构的培训、咨询以及交付工作。实际上,传统企业在过去多年的业务积累中,由于组织架构、业务发展和市场竞争等综合因素,技术体系相对封闭,缺乏快速交付的理念。因此,微服务的出现,加之社区的热捧,导致很多传统的团队过于追热而并没有完全理解微服务。
经过2015年的快速普及,微服务的优势被越来越多的传统组织和企业所认可,但由于架构相关的知识本身比较抽象,虽然各大会议上有很多互联网公司的案例分享,但开发者似乎依然很难全面了解微服务架构。
所以,希望通过本系列的文章以及视频,以一个真实的案例为背景,以持续交付和DevOps为主线,帮助初学者理解微服务架构,并能通过动手实验,了解相关的实践以及方法论。
精彩视频课程已经出炉,请移步这里
[如需转载,请联系本人]
过去的几个月,我作为独立咨询师,为多个传统企业提供了微服务架构的培训、咨询以及交付工作。实际上,传统企业在过去多年的业务积累中,由于组织架构、业务发展和市场竞争等综合因素,技术体系相对封闭,缺乏快速交付的理念。因此,微服务的出现,加之社区的热捧,导致很多传统的团队过于追热而并没有完全理解微服务。
经过2015年的快速普及,微服务的优势被越来越多的传统组织和企业所认可,但由于架构相关的知识本身比较抽象,虽然各大会议上有很多互联网公司的案例分享,但开发者似乎依然很难全面了解微服务架构。
所以,希望通过本系列的文章以及视频,以一个模拟的案例为背景,以持续交付和DevOps为主线,帮助初学者理解微服务架构,并能通过动手实验,了解相关的实践以及方法论。
精彩课程已经出炉,请移步这里
过去的1年多,一直在助力澳洲最大的房地产互联网门户,研究并使用微服务架构改造其复杂的遗留系统。鉴于此,准备开个系列,讲讲我个人眼中的微服务是神马样的,它的概念,优缺点,为什么我们要使用它,以及在使用微服务的实践过程中,从开发、测试、部署、运维等几个方面相比以前方式有什么不同;同时,分享一下我们在微服务实践过程中的经验和踩过的那些坑。
[请勿转载]
#单块架构系统以及其面临的挑战
多年来,我们一直在技术的浪潮中乘风破浪,扬帆奋进,寻找更优秀的方法来构建IT系统,也一直在积极的学习并观察先进的公司如何以不同的架构方式构建或者优化其IT系统,来积极应对市场的变化,迅速做出响应,从而为客户提供更多的价值。
微服务架构模式(Microservice Architect Pattern)是近两年在软件架构模式领域里出现的一个新名词。虽然其诞生的时间不长,但其在各种演讲、文章、书籍上所出现的频率已经让很多人意识到它对软件领域所带来的影响。那到底什么是微服务,当我们谈论微服务时,它代表着一种什么样的含义?微服务适合应用在什么场景下,以及它有什么样的优缺点?微服务和SOA到底有没有区别?在接下来的几部分里,我将为大家揭开微服务的神秘面纱。
[请勿转载]
什么是核心特征,就是当我们谈论同一件事情的时候,那些不同的人们所关注的相同的部分。从业界的讨论来看,微服务通 常有如下几个显著特征:
一直以来,我们都比较提倡使用组件(Component)的方式,模块化应用系统。它类似生活中的汽车,由不同的零件组成,每个零件都是可以独立替换的。因此,这类通常都有很好的灵活性和替换性。
在软件领域,我们也将组件定义为应用软件构建中独立的单元,它的最大特点是,对整个应用软件而言,组件能够被容易的替代或者更新。
传统实现组件的方式是采用和应用程序一样的的编程语言,构建独立的共享库(Libaray),从而达到解耦和复用的效果。对于共享库而言,我们知道它是语言相关、平台相关,并且是和应用程序运行在同一个进程中的,因此,任何共享库的变化都意味着整个应用程序也要被更新,并且需要被重新部署。换句话说,如果应用由多个共享库组件组成,那么任何库的变更都将导致整体应用的重新发布。
[请勿转载]
在上一章中,我们认识了什么是单块架构应用,并分析了随着互联网时代的快速发展,随着市场变化快,用户需求变化快以及用户访问量的增加,单块架构应用的维护成本、人员的培养成本、缺陷修复成本以及技术架构演进的成本和系统扩展成本等都在增加,因此单块架构曾经的优势已逐渐无法适应互联网时代的快速变化,面临着越来越多的挑战。
在本章中,我们来了解到底什么是微服务架构,以及为什么微服务架构能有效解决单块架构在互联网时代所面临的挑战。
微服务架构一词在过去几年里,得到了广泛的讨论和关注。微服务架构提倡通过对特定业务领域的分析与建模,将复杂的、 集中的、耦合度高的应用系统分解成小而专、耦合度低并且高度自治的一组服务。这些服务与服务之间相互协作、相互配合,从而为最终用户或其他系统提供相应的功能。微服务将每个独立的业务逻辑划分出来,运行在它们自己的进程中,然后通过分布式的网络互相通信与协作,从而为终端用户或其他调用者提供灵活的接口。
[请勿转载]
将单块架构应用分解为一系列相对独立的微服务,其中每个服务都运行在自己的进程中,并且通过轻量级的机制实现彼此间的通信,这通常是HTTP资源的微服务。这些服务是围绕着业务功能构建的,并且可以通过完全自动化的部署机制进行独立部署。这些服务的集中式管理做到了最小化,每一种服务都可以通过不同的编程语言进行编写,并且可以使用不同的数据存储技术。
本文已经发表于InfoQ,请参考这里
##背景与挑战
随着公司国际化战略的推行以及本土业务的高速发展,后台支撑系统已经不堪重负。
在吞吐量、稳定性以及可扩展性上都无法满足日益增长的业务需求。对于每10万元额度的合同,从销售团队准备材料、与客户签单、递交给合同部门,再到合同生效大概需要3.5人天。随着业务量的快速增长,签订合同的成本急剧增加。
合同管理系统是后台支撑系统中重要的一部分。当前的合同系统是5年前使用.NET,基于SAGE CRM二次开发的产品。 一方面,系统架构过于陈旧,性能、可靠性无法满足现有的需求。另一方面,功能繁杂,结构混乱,定制的代码与SAGE CRM系统耦合度极高。
由于是遗留系统,熟悉该代码的人早已离职多时,新团队对其望而却步,只能做些周边的修补工作。同时,还要承担着边补测试,边整理逻辑的工作。
在无法中断业务处理的情况下,为了解决当前面临的问题,团队制定了如下的策略:

One of the most prominent and widely used languages in the world has Evolved.
Java ever gave us power on object oriented progrmming and we did the best we could with it.
Now there’s another new elegant way changing the java world-Lambda Expression, that will make our code more expressive, easier to write, less error prone, and easier to parallelize than has been the case with Java.
###Lambda Expression Let’s start from a simple example:
Asgard is named for the home of the Norse god of thunder and lightning. As the words described, it is closely relevant to the management and control in cloud.
Netflix build a tool named Asgard, which is used to control and manage their AWS cloud. In 2012, Netflix announced that Asgard was open-sourced.
Then…… it is time to start the story.
##What is Asgard
Asgard is a web-based tool for managing cloud-based applications and infrastructure.
Application and Cluster terminology, enable users understand their cloud objets clearly.Recently, our team is moving several legacy components running in Windows server from data-center to AWS. The transformation itself is not hard, but the eco-system like monitoring, alerting, troubleshooting is most important before getting started the transofrmation.
The article would talk about how to setup and config Splunk Universal Forwarder in Windows machine where the component is running.
Bying using SUF, Splunk central server can easily collect logs from different distributed machines, so that the OPS guy can query and analyze the logs from one portal rather than login on different distributed machines.
To simulate the process of production deployment of MongoDB, I used Vagrant to create a couples of VMs, and exprienced the journey of deployment mongo step by step as follow mentioned.
Before dived into the code, we can review the concepts related to Mongo Shard, it needs 3 components logically at least.
The config server processes are mongod instances that store the cluster’s metadata. You designate a mongod as a config server using the –configsvr option. Each config server stores a complete copy of the cluster’s metadata.
The query server are lightweight mongos instances and do not require data directories. You can run a mongos instance on a system that runs other cluster components, such as on an application server or a server running a mongod process. By default, a mongos instance runs on port 27017.
mkdir -p /srv/mongodb/rs0-0 /srv/mongodb/rs0-1 /srv/mongodb/rs0-2
mongod --port 27017 --dbpath /srv/mongodb/rs0-0 --replSet rs0 --smallfiles --oplogSize 128
mongod --port 27018 --dbpath /srv/mongodb/rs0-1 --replSet rs0 --smallfiles --oplogSize 128
mongod --port 27019 --dbpath /srv/mongodb/rs0-2 --replSet rs0 --smallfiles --oplogSize 128
mongo --port 27017
rs.initiate()
rs.conf()
rs.status()
趁着在墨尔本和西安Office上Hackday获奖的喜悦劲,赶紧来一篇Dora诞生记。
提醒偶记住这个特殊的日子,同时也感谢在过去两个月,牺牲个人时间,奋斗在Dora(X-Robot)上的Casa的兄弟姐妹们。
#####-2013年10月20 和Charley午餐的时候,无意间谈论起了各自想做但没时间做的idea。
幸运乎,找到一个我俩都认为不错但又没被完全实现的一个想法«公交来了»(旨在帮助等车族们准确的掌握公交将来的时间,为既不想迟到又想多赖几分钟在床上的兄弟提供福音)。
在上篇文章里,我们已经了解了MediaStream。那么这篇文章里,我们就来重点了解RTCPeerConnection。
RTCPeerConnection表示浏览器之间点对点的连接。只有当连接建立后,浏览器的两端才能真正完成流媒体数据的传输。
还记得之前讨论过的WebRTC架构图吗? 实际上,虽然RTCPeerConnection是一个暴露的连接接口, 但其内部封装了大量WebRTC编解码和协议处理的工作,因此使浏览器之间点到点的即时通讯变得简单。
WebRTC从设计之初,目的就是为开发人员提供更加简便的方式构建基于Web的视频、音频应用。对于任何的WebRTC应用程序,只需要做如下几件事情:
###什么是WebRTC
如今,互联网主流的音频、视频通信服务产品,如Skype, QQ, GTalk等, 都是各自厂商私有的技术。用户需要安装插件或者桌面客户端,才能使用其提供的音频或者视频通信功能。 如果某天,不使用任何插件,只通过浏览器,就能实现手机、平板、电视和电脑的视频或者音频通信;那会是什么场景? 而这正是WebRTC的愿景。
WebRTC(Web Real-Time Communication)由一套开放的标准、协议和一组JavaScript API构成。2010年,谷歌收购了VoIP软件开发商GIPS(Global IP Solutions),并获得了视频采集、编解码、网络传输、回音消除等RTC相关技术。2011年6月,谷歌开放了该部分源码,并积极推动该项技术,这奠定了RTC在Web领域发展的基础。
WebRTC使浏览器之间能够通过点对点的通信方式,直接完成视频、音频以及数据的实时传输。同时,WebRTC容许开发人员通过调用浏览器支持的API,使用HTML5标签和JavaScript轻松的实现基于Web的音频、视频应用。
目前,WebRTC的标准还在不断完善中,W3C、IETF和其他一些浏览器厂商正在积极的推动WebRTC的发展。WebRTC开创了浏览器之间能够直接通信并完成视频或者音频传输的新时代。对于构建开放的、标准的,无插件,免费的视频音频通信应用,迈出了划时代的一步。
##什么是Page Object Page Object是Selenium中提出的一种测试设计模式。在Web前端自动化测试的过程中,Page Object可以称得上是居家必备的良品之一。PageObject将与Web测试页面交互的行为封装在其内部,旨在将每个页面或者相似页面的功能封装,例如页面中需要测试的元素(按钮,输入框,标题等),这样,通过在测试中访问Page类的相应方法来获取页面相应的元素,从而巧妙的避免了当页面元素id或者位置变化时,需要修改测试代码的情况。
言而总之,总而言之,PageObject就是将Web页面元素的变化封装起来,提供API供外部测试代码调用,从而达到将测试代码于Web页面元素的变化解耦。
顺应Open Hardware的潮流,Team里最近买了块 Arduino的板子。于是乎,偶也就有个机会,能倒腾倒腾了。
Arduino 是一个开源、易于使用的硬件设备。其上的微控制器可以通过Arduino Style的编程语言来编写程序,编译成二进制文件,并烧录进微控制器。 Arduino 能通过各种各样的传感器来感知环境,通过控制灯光、马达和其他的装置来反馈、影响环境。和传统的单片机有点类似,但是更易于使用,对于开发者也更加友好。

Mockito是一个方便的java测试Mock工具。
当我们做TDD或者单元测试的时候,为了消除当前被测对象和其依赖之间的关系,经常使用Mockito。
本篇文章只涉及如何使用Mockito的Partial Mock。关于Mockito的其他用法,请参照Mockito
###1. 什么是Partial Mock 在单元测试的过程中,偶尔会出现这种情况。对于一个对象,某些方法需要被mock,而某些方法希望被直接调用,这时候,我们就需要借助Partial Mock。
###2. 使用Partial Mock的场景
在如下两种场景中,Partial Mock就显得相当犀利:
public abstract class AbstractHandler {
public String greet() {
return "Hello " + fetchName() + "!";
}
protected abstract String fetchName();
}
如上代码所示,抽象类AbstractHandler中定义了方法greet(),并且该方法存在一定逻辑。 此时,如果希望测试greet(),可以选择两种方式:
public class AbstractHandlerTest {
@Test
public void shouldCallRealMethodsAndFakeAbstractMethod() {
AbstractHandler handler = mock(AbstractHandler.class);
when(handler.greet()).thenCallRealMethod();
when(handler.fetchName()).thenReturn("Geek");
assertThat(handler.greet(), is("Hello Geek!"));
}
}
如代码所示,对于抽象方法fechName(),直接mock其返回值 when(handler.fetchName()).thenReturn(“Geek”);
对于被测方法greet(),则使用thenCallRealMethod()使Mock对象调用真实的实现方法。 when(handler.greet()).thenCallRealMethod();
public class BooksController {
protected Map<String, Date> fetchBooks(){
//fetch the books from different publishing company.
service1.retrieveBooks();
service2.retrieveBooks();
......
service10.retrieveBooks();
}
protected List<String> getPublishedBooks(){
books = fetchBooks();
//only pick up the books published.
}
}
如上代码所示,类BooksController中定义了方法fetchBooks(),并且该方法严重依赖于I/O操作。因为fetchBooks()从不同的供应商那里获取最近的书籍信息。
###如何安装应用
当我们第一次使用Box创建VM时,它通常是个没有装太多应用的裸机。所以,就会面临一个问题: 如何快速并有效的安装工作需要的软件,如数据库、Web服务器等?
目前,基本上有两种方式:
####手动安装
###什么是Vagrant Box
谈论完了Vagrantfile,让我们看看Vagrant的另外一个重要概念Box。它是Vagrant运行VM的必要条件。
基本上,从头开始建立一个VM是相当耗时的工作,于是Vagrant使用一个基础映像(base image), 克隆它并快速创建一个可用的VM。
在Vagrant的世界里,所有这些基础映像统称为Box。简单地说,Box可以理解为创建VM时需要的模板,通过这些模板,我们可以创建VM。
###Vagrantfile
Vagrantfile是Vagrant启动并设置VM的配置文件,每个VM都必须有一个Vagrantfile。
当执行Vagrant init,Vagrant便会帮我们生成一个默认的Vagrantfile。
当然,不同的VM可以根据需求更改Vagrantfile的配置信息。
对于开发团队,我们可以将Vagrant配置文件放入版本管理系统,从而整个团队能够共享并不断改进该文件,在团队内部提供一种方便快捷的方式,构建产品运行环境。
譬如,我们可以执行如下代码生成Vagrantfile
mkdir vm && cd vm
vagrant init precise64 http://files.vagrantup.com/precise64.box
Vagrant会提示
A Vagrantfile has been placed in this directory. You are now
ready to 'vagrant up' your first virtual environment! Please read
the comments in the Vagrantfile as well as documentation on
'vagrantup.com' for more information on using Vagrant.
查看当前目录,会发现Vagrantfile已经生成。
###背景介绍
最近的Java项目是个同海外团队合作的遗留系统,包括数据库服务器、邮件服务器、Web服务器、FAST搜索引擎、JBOSS中间件等等节点。为了便于团队使用,我们在Amazon 的EC2上建立了一套完整的端到端的运行环境。
团队成员在本地搭建了Web环境,数据库环境,便于开发及调试。但由于Mac上安装FAST并不是一件易事,因此在本地跑应用的时候依赖于Amazon EC2的FAST节点。
持续集成、CI在当今的时代已经不是什么新鲜玩意了,越来越多的团队已经了解并运用在实践中。对于我们和海外客户共同开发的这种情况,CI挂了可不是太好,因此在每次提交代码之前,需要确保本地所有的测试都能通过,才能提交代码。
于是乎,问题就来了:
TWU32届的Trainer陆陆续续的都撤了,于是乎,我们就有了机会搬进他们的House,Pune的人民称之为"Bungalow",实际上我觉得是个2层的别墅。
有趣的事情来了,我们住得bugalow,我之前两次没记住具体的地址,以至于做三轮车的时候都和师傅说不太清楚。某天一个同事给我说,你就这样说bungalow的地址"guo de gao park",oh my god,这下我记住了,“郭德纲 park"。其实原本的拼写是这样的“Koregaon Park”,发音有那么一丁点类似而已 :)

还在墨尔本出差的最后一周,Mark问我愿意去TWU当coach不…….于是乎,我就在8月中旬来了浦那(Pune)。一路上同行的还有JK和邱大师,中午从西安出发,先抵达香港,再转机到班加罗尔时已经是第二天凌晨5点多,又搭乘印度国内的航班,总算在早上10点多下榻酒店。
浦那位于印度西部的城市,位于孟买东南140公里,设有不少学院及大学,素有「东方牛津」的美名。城内有著名的Magapatta City软件园和塔塔汽车公司。
Pune的基础建设比想象中落后些,基本上都是单向双车道,挤满了各类车辆,卡车,私家车,中巴车,这种情况下,当然小巧方便的摩托车和三轮车更胜一筹。钻来钻去,穿梭在大大小小的缝隙中,我想这也是为什么摩托车和三轮车成为主要交通工具的原因之一。道路的两边并没有明显的划分出人行道,大概能走的部分可能不到半米宽。除了在主干道的十字路口见到一组红绿灯,其余的道路基本没有红绿灯,过马路绝对是个不小的挑战。千万记得,是看左边哦 :)
Shalina安排的很周到,抵达的第一天,就给我们发了大礼包(有手机,充电器,耳机,还有印度地图和SIM卡),哈哈,最重要的当然就这张SIM卡了。这里赞一下小米,无缝即插即用,邱大师的IPhone就没这么幸运了,和他找了个地方花了100卢比把卡裁的小点,也能使了。不过赞一下,印度人民的服务真是不错啊,相当仔细嘞。
住了几天Keys Hotel后,公司决定把我们搬到O Hotel, 因为TWU的培训地就在O hotel。O hotel的电梯设计的很别致,很难想象这是电梯的顶部装修吧(有漂亮的小星星哦),而且还有优美的旋律伴奏。

早餐很精致,有水果,煎蛋还有各种干货,哈哈。午饭一般就是米饭和印度传统的鸡肉糊糊,不过汤有时候还是蛮不错的,毕了,还有各种甜点。
TWU的培训地点就在2楼,上午10点半和下午的3点半,提供咖啡、茶、牛奶和甜点。
前面2周主要都是TTT(Train the Trainer),就是我们新来的小样接受以前Trainer的培训。到下午6点,结束了一天的培训,基本上就可以自由活动了。哈,Pune有很多有趣的东西等着我们explore呢……
bash < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer) rvm install 1.9.2 rvm use 1.9.2 –default
git clone git://github.com/imathis/octopress.git octopress
gem install bundler bundle install bundle update # 不执行,则下一步rake会报版本不匹配 rake install rake setup_github_pages
rake new_post[“My first post”] rake generate # 第一次使用,最好先编辑一下_config.yml
rake preview # 本地查看,地址是http://localhost:4000 rake deploy
git commit -m ‘your message’
git push origin source
##什么是Module Pattern?
Javascript,是面向对象但并不是面向对象编程的一门语言。在Javascript的世界里,你遇到的所有东西都是对象(如Function, Number, String等),但它本身的语法中却不提供类(class)的关键字或者访问符(private, public, protected)等的定义。
不过,通过使用Module Pattern,我们可以有效的筑起一道屏障,让私有状态的变量或者方法只能在module的内部被访问,从而达到面向对象封装的目的。
在这篇文章中,我将介绍Javascript中变量的作用域以及变量提升的一些相关知识。
##变量作用域 变量作用域是指变量存在的上下文环境,它表明了当定义一个变量后,代码如何能够访问该变量。基本上,Javascript的变量有两种: 局部变量和全局变量(废话,哪门语言没有这两种!)
工作在*nix环境下的兄弟们,多多少少都应该见过这么几个文件:
/etc/profile
/etc/bashrc
~/.bash_profile
~/.bashrc
~/.bash_login
说实话,我一直没搞清楚这些文件是干什么的,以及他们是什么联系。今天组里正好有人讲这个,就给自己长长见识吧。其实吧,最主要的区别就在于两个词: “Login shell” 和 “Non-login shell”。
一直以来,我对Javascript都不是怎么感兴趣,主要的原因还是由于JavaScript 和浏览器之间复杂的历史渊源,导致javascript被浏览器严重束缚。 不过,Node.js的出现,让我看到了一种全新的使用JS的方式(启动、调试等可以完全不care浏览器)。经过几天对Node的了解,发现Node确实有一些与众不同的特点。
####1. The Brain(http://www.thebrain.com/) 现在的新知识越来越多,体系越来越庞大,非常需要the brain这样一个软件,将所学的知识分门别类,形成一个整体的、宏观的脑图。
####2. Trello(https://trello.com/)
一个方便的电子卡片墙,帮助你记录想做的事,正在做的事,或者已经完成的事,同时提供了Android和Iphone上的支持。
在我们使用Gradle构建项目的过程中,免不了要经常和文件打交道,譬如文件拷贝、文件重命名、生成压缩包等。在这方面,Gradle已经提供了非常好的支持,下面我们就来尝试一下如何使用Gradle提供的方式,操作文件或者目录。
###1. 文件访问 ####1). 访问单个文件或者目录
file()将帮助我们访问相对于当前project的文件或者目录,注意不是相对当前的工作目录。因为我们有可能通过参数-p指定运行Gradle脚本的目录,而并不一定非要进入到该目录后再运行gradle。譬如在下面的例子中,当前工作目录是home目录,而gradle当前project的目录则是~/work/project1/ ~> gradle -p ~/work/project1 tasks
随着信息化的快速发展,IT项目变得越来越复杂,通常都是由多个子系统共同协作完成。对于这种多系统、多项目的情况,很多构建工具都已经提供了不错的支持,像maven、ant。Gradle除了借鉴了ant或者maven的继承的方式定义子项目,也提供了一种更为方便的集中配置的方式,大大减少了构建带来的复杂度。除此之外,Gradle还提供了清晰的Project树模型来映射多项目的组织结构。下面,让我们了解一下如何使用Gradle构建多项目。
###1. 多项目定义及结构
在Gradle中,使用文件settings.gradle定义当前项目的子项目,格式如下所示:
include ‘sub-project1’, ‘sub-project2’, ‘sub-project3’, 它表示在当前的项目下建立三个子项目,分别为’sub-project1’, ‘sub-project2’, ‘sub-project3’。默认情况下,每个子项目的名称对应着当前操作系统目录下的一个子目录。
上一篇文章中,我们提到了Gradle的一些基本概念,如Project、Task以及Action,并且创建了我们的第一个Task。这次我们来看看Gradle中关于Project和Task的更多细节。
###1. Project和Task
对于build.gradle配置文件,当运行Gradle
println "the project name is $name"
task hello << {
println "the current task name is $name"
println "hello world"
}
###前提: 安装Gradle 安装过程非常简单:
(1)下载Gradle (2)设置GRADLE_HOME (3)将GRADLE_HOME/bin/gradle加入$PATH
###1.基本概念(Project 和 Task)
Gradle中有两个基本的概念:project和task。每个Gradle的构建由一个或者多个project构成(有且仅有一个root-project以及多个可能存在的sub-project),代表着需要被构建的根项目以及可能包括的多个子项目。每个project由一个或者多个task组成,而task则是Gradle构建过程中可执行的最小单元。譬如,当构建一个Java项目时,可能需要先编译、打包、然后再发布,这其中的每一个动作,都可以定义成一个task。
###2.构建第一个Task 和Ant运行时读取build.xml类似,Gradle运行时默认会读取build.gradle这个文件, 当然你也可以使用参数"-b"来指定其他的gradle文件。
下面,让我们新建一个build.gradle文件,然后输入如下内容:
task hello {
doLast{
println "hello world"
}
}