工欲善其事必先利其器(二)—–vagrant

学会使用虚拟机之后,那么我们一定会面临一个比较棘手的问题:我们应该如何来管理这些虚拟机?因为我们常用的虚拟机都是配置好的,熟悉的环境,熟悉的工具。重复配置无疑是一种浪费时间的行为,为了避免这种浪费,那么我们需要一个强有力的工具vagrant.

什么是vagrant

Vagrant is a tool for building and managing virtual machine environments in a single workflow.

来自于官方的说法,vagrant就是专门用来建立和管理虚拟机环境的工具。

vagrant是用ruby语言编写的,在vagrant中所有的虚拟机环境都来自于一个叫做box的文件,通过 配置Vagrantfile,指定需要使用的box,然后配置cpu核心数量,内存大小,网络,共享文件,登录凭证等信息,可以快速的得到一个已经配置好的虚拟机环境。其实大多数配置都是可以省略的,最便捷的配置文件甚至只有一条配置。

什么场景下应该使用vagrant

抛开场景谈工具都是耍流氓,每一种工具都有它最适合存在的地方。虽然平时作为个人使用的时候,我们大多用来迁移和管理自己的虚拟机,但是我觉得它最实用的地方就是“团队协作”。每个人都会有自己的使用习惯,有些人习惯mac,有些人习惯linux,还有人则习惯用windows。哪怕同样用的是windows,也有win7和win10等各种区别,就算同样用的win7或者win10,那么大家用的IDE也可能都是不一样的。linux更不用说了,对应着各种不同的发行版。这个时候vagrant的强大就体现出来了,不管用户所使用的操作系统是何种类别,都能保证开发环境的一致性。这样可以避免开发过程中,因为环境不一致所带来问题。

获取vagrant

vagrant下载页,  可以获得最新版的vagrnat版本,有debian,windows,centos,mac.arch linux等各种版本可以选择,如果是ubuntu操作系统的话,除了可以使用debian的deb安装包来安装,还可以使用apt命令进行安装

sudo apt install vagrant

不过通过apt安装的vagrant版本不是最新版本,请酌情使用

vagrant操作

vagrant操作系统的基本操作非常简单,只有简单的几条命令

vagrant init  初始化虚拟机

vagrant up 启动虚拟机

vagrant provision 应用虚拟机配置

vagrant halt  关闭虚拟机

vagrant destroy 摧毁虚拟机

vagrant ssh  进入虚拟机终端

获得vagrant官方基本系统环境hashicorp/precise64的方法非常简单,只需要运行命令


vagrant init hashicorp/precise64
vagrant up

就可以获得一个基础的虚拟机环境了,不过需要注意的是,因为vagrant的box有时候体积比较大,在执行下载的过程中可能会非常缓慢甚至是没有办法获得资源的情况,如果在运行命令的过程中出现超时或者卡主的情况,可以在后面找到解决的办法

vagrant的box

vagrant官方提供了一系列的box下载,在下载页中,支持最多的虚拟机就是virtualbox,

vagrant中添加box的命令如下

vagrant box add  box名称 box路径     ps:可以是网络路径或者是本地路径

可以添加本地路径的box,那么我们可以先从下载页把box下载到本地,然后本地环境添加hashicorp/precise64,接着执行

vagrant init hashicorp/precise64
vagrant up

就能快速得到一个可用的虚拟机环境了

如果要查看当前可用的box,可以使用命令
vagrant box list

制作属于自己的box

box除了可以从网上获取之外,还自己制作,除了可以从无到有制作一个box,还可以在已有的box之上,添加一些定制功能,把它变成只属于自己的box

在vagrant中有一条命令,可以打包属于自己的虚拟机

vagrant package --base 虚拟机标识 --output box名称

ps:虚拟机标识不是在虚拟机页面显示的名称,这个标识需要通过命令vboxmanage list vms来得到,其中vboxmanage命令是virtualbox自带的工具,如果是其他虚拟机的话,则需要其他工具来获取

在使用vagrant中可能会遇到的问题

  • 在执行vagrant up过程中,出现超时或者卡住的现象,这个是因为网络的问题,因为在国内的网络速度不是很给力,而且还有GFW的存在可能没有办法获取到资源,不过这个可以通过添加本地box的方式或者通过科学上网工具来解决
  • vagrant up过程中,ssh配置失败,这个现象发生的原因有很多种,调试方法是打开gui选项,看看是否出现故障,其次是可以通过ssh vagrant@ip  password:vagrant 登录到虚拟机 手动配置ssh权限即可
  • 更多问题请仔细阅读vagrant官方文档,或者通过stackoverflow寻找解决方案

 

 

正则表达式

今天在 使用awk工具处理日志的时候,需要捕获ip地址进行分类,于是随手就写了一个匹配ip的正则((\d{1,3})\.){3}\d{1,3},但是在匹配的时候发现没有任何反应,仔细检查并测试之后,发现并不是我写的正则有问题,而是这是一个历史遗留问题。

正则表达式的种类

纵观整个Regular Expression(正则表达式)的历史,你就会发现,正则表达式是有一个发展过程的,像我上面写的((\d{1,3})\.){3}\d{1,3}这样的正则表达式,其实是比较现代的正则表达式,也就是Perl的正则表达式(Perl Regular Expression),简称PREs。但是在PREs出现之前,人们常用的是BREs(基础正则表达式),和EREs(扩展正则表达式)。

三种正则表达式的区别

如果单从语法的角度看,三种正则表达式并没有多大区别,都是由元字符+普通字符组成,其中元字符“ ^ $ . * + ?  ()  [] {} \ ” 这些基本的元字符都包含在内,这些元字符是正则表达式的基础,但是BREs基础正则表达式对于“* + ? () {}”的支持是需要转义才能使用的,比如在PREs中[0-9]{1,3}匹配1-3个0-9之间的数字,在BREs中的写法则是[0-9]\{1,3\}。

EREs和PREs在“ * + ? () {} ”的使用上则没有什么不同

在PREs中,我们常常使用\d \s \t \n \f \num 等等这种带有转义性质的特殊元字符,在BREs和EREs中是不 支持的

awk sed grep对三种正则表达式的支持

在linux命令行下,我们常常用的awk sed 以及grep命令,默认支持的都是BREs(基础正则表达式),不过grep带上参数之后可以提供对PREs和EREs的支持(grep -P, grep -E),如果习惯使用PREs的话,可以对grep 加上别名

alias grep = "grep -P"

解决方案

了解了三种表达式的区别以后,想要解决之前出现的问题,就非常简单了,只需要把(\d{1,3}\.){3}\d{1,3}改成(\d{1,3}\.)\{3\}\d\{1,3\},就解决了问题了。

正则表达式是一种强大的工具,我觉得任何一个程序员都应该熟练掌握它。

工欲善其事必先利其器(一)—–虚拟机

作为一名程序员,大多数时候都是在自己熟悉的环境里工作,永远是熟悉的操作系统,熟悉的那个IDE,熟悉的那个环境,仿佛一切都那么自然。但是如果永远是这样的话, 那么生活就显得太安逸了,实际生活中我们总会遇到各种各样复杂的情况。比如说,我们常常在windows或者是mac下工作,但是有些时候服务器的环境往往都是linux,为了熟悉服务器上的环境,我们必须要去熟悉并且灵活这种工具。但是在现实生活中,拥有多台物理机的成本还是相对于普通人来说,还是比较昂贵的,这个时候使用虚拟机把现有的硬件进行虚拟化来达到拥有多台计算机的效果就显得十分有必要了。

使用虚拟机的情景

  • 宿主机是windows或者mac,想要学习linux或者是unix
  • 沙箱环境,构建一个和本机相同环境的沙箱,当需要运行一些可能对计算机造成损害的软件的时候,先在沙箱中运行检查软件是否有危害,而后迁移到本机上,保证计算机的安全性
  • 工作环境迁移,一个用的十分熟练的系统必定是经过自己打磨许久之后逐渐磨合的一个超级工具,装了很多熟悉的软件,到一个新的环境下 之后,重新安装上这些东西会非常的麻烦,但是如果选择在虚拟机里进行工作的话,就可以在任何地方迅速的搭建起熟悉的环境

虚拟机软件常见的种类

  • Vmware ,横跨windows,linux,mac各种平台(注:在mac下叫FUSION,其他平台一般叫WORKSTATION),性能强大,功能齐全,唯一不足的地方就是价格了,每个月$249.99,多0.01美金就是250了
  • Hyper-V, 微软的产品,采用hypervisor的技术,据说可以和Vmware比肩,优点非常明显,windows自带,直接开箱即用,但这也是最大的缺点,只能在windows下用。
  • parallels,mac用户的福音,mac下的专属软件,可以非常方便快速的在mac下执行windows软件,价格每年$79.99,不算很贵,缺点就是只能在mac下运行。
  • VirtualBox,我最钟爱的虚拟机软件,强大的跨平台能力,支持windows,linux,mac,solaris等各种平台,体积轻巧,并且开源信仰。

不一样的VirtualBox

尽管virtualbox在功能上来说,它没有vmware那么强大,并且对于windows用户来说没有内置的Hyper-v来那么方便快捷,但是它拥有的特性:开源,跨平台,对我来说都有着深深的吸引力,我觉得对于大部分人来说都是一个非常好的选择,而且如果使用vagrant的话,就更能体会到它的优势所在了

  • 获取virtualbox

virtualbox的安装包可以在virtualbox的官方下载页获得

ubuntu用户可以通过apt工具来获得

sudo apt update

sudo apt install VirtualBox-5.2

centos用户可以直接通过yum工具来获得

yum install VirtualBox-5.2

使用virtualbox需要注意的地方

  • 虚拟硬盘,使用virtualbox创建虚拟硬盘的时候有三个选项,分别是VDI,VHD,VMDK,其中VHD是微软虚拟磁盘文件,一般应用于virtual PC,而VMDK则是由vmware创建的磁盘,如果创建这种磁盘可以共享给vmware使用,而VDI则是virtualbox自己创建的虚拟硬盘了,如果没有特殊需求的话,只要选择VDI类型的磁盘就可以了
  • 网卡,在virtualbox中的网卡有6种,分别是网络地址转换(NAT),NAT网络,桥接网卡,内部网络,仅主机(host-only)网络,通用驱动。

网络地址转换和NAT网络的区别并不是很大,都是把主机当成路由器来使用,同一网段下的多个虚拟机之间可以相互访问,并且虚拟机能访问到外部网络,包括互联网

桥接网卡则是把虚拟机当成局域网下一台真实的主机一样使用,使用桥接网卡的虚拟机可以使用宿主机相同网段的ip地址,并且可以让局域网下其他的计算机访问到

内部网络是虚拟机自成网络,虚拟机内部可以互相通信,但是不能对外,也不能访问互联网

仅主机网络,相当于用一根网线把虚拟机和主机连接起来,相互可以访问,但是如果需要访问其他地方的话,则需要其他配置

多种网卡有所区别,但是在virtualbox中是可以配置多块网卡的,所以使用还是非常方便的

使用virtualbox可能遇到的问题

  • 虚拟机不能全屏

virtualbox的安装目录下,有名为VBoxGuestAdditions.iso的镜像文件,这是virtualbox的增强工具,只有安装了增强工具的虚拟机才能使用文件夹共享,目录同步,虚拟机全屏等一些扩展功能

  • 不能选择64位操作系统的虚拟机

造成这个原因的极有可能是,在bios没有开启cpu的虚拟化功能,修复这个操作需要进入到bios开去cpu 虚拟化,不同的硬件厂商标准不一样,这里不多介绍

  • 虚拟机中复制的文件或者文字不能粘贴到宿主机

打开虚拟机设置,在常规选项》高级, 启用共享剪切板和拖放功能

  • 虚拟机卡顿不流畅

需要多分配一些内存给虚拟机,虚拟机和真实的电脑差不多,也是需要消耗计算机资源的

结语

如果用来学习多个操作系统的话,除了选择虚拟机之外,还可以使用双系统,双系统的优势是两个操作系统都可以享受完整的计算机cpu和内存等资源,而且互不干扰,缺点就是两个系统不能同时启动,而使用虚拟机的话,那就意味着你的电脑配置相对来说需要好一点。如果计算机的配置不是很高的话,还是推荐使用双系统。

解决前端跨域的方法

引言:由于浏览器的安全性能问题,导致ajax非同源请求无法访问,但是有些时候我们必须要用到这一功能,所以整理出四种层面不同思想来解决这个问题

 

一、Javascript

在javaCript层面,有一种耳熟能详的手段来解决跨域问题,那就是jsonp,原理是在客户端注册一个callback函数,然后把callback的名字传给服务器,此时,服务器先生成 json 数据。
然后以 javascript 语法的方式,生成一个function , function 名字就是传递上来的参数 jsonp.
最后将 json 数据直接以入参的方式,放置到 function 中,这样就生成了一段 js 语法的文档,返回给客户端。
客户端浏览器,解析script标签,并执行返回的 javascript 文档,此时数据作为参数,传入到了客户端预先定义好的 callback 函数里.(动态执行回调函数)

 

二、Php

在html直接请求同源地址的接口文件,如api.php,然后在api.php中利用curl扩展去请求需要请求的页面获取相关数据,然后返回给前端页面,这种方式相当与代理,利用本地同源的页面去请求非同源页面

 

三、HTML5

HTML5之前的标准是没有办法进行跨域的,但是但HTML5中新增加的特性可以实现这一功能,通过设置Access-Control-Allow-Origin头可以在页面中允许特定页面或者所有页面的请求,在php中可以使用header函数设置

header('Access-Control-Allow-Origin:*');

 

四、Nginx

Nginx服务器层面的解决方法和php中类似,也是代理模式,前端页面请求同源地址,然后用nginx重写规则将此请求代理到需要请求的非同源页面,达到一种欺骗浏览器的效果。

 

尾语:部分浏览器经过设置以后也可以解决跨域问题,但是作为程序员,我们不能把希望寄托在用户的身上,所以还是从上述解决方案中挑选为佳

javascript生成随机数

引子:
在写程序间突然需要用到随机数,于是用到了js的Math.random随机函数,生成指定范围内的随机数,根据网上流传的写法生成指定范围内的随机数如下

function random(min, max){
    return Math.round(Math.random()*(max-min))+min;
}

var zero = one = two = three = 0;
for(var i=0;i<10000;i++){
    var num = random(0,3);
    if(num==0){
        zero++;
    }else if(num==1){
        one++;
    }else if(num==2){
        two++;
    }else if(num==3){
        three++;
    }else{
        console.log("assert false");
    }
}
console.log(zero,one,two,three);

经过10000次计算,在0-3范围内生成的结果数据如下,0=1670次 1=3348次 2=3266次 3=1717次
发现这个算法略坑,min以及max的边界命中率简直低的可怜,并不是一个均匀分布,而是正态分布,为了满足需求,只能对算法进行重写了

Math.random()函数

根据官方的定义:random() 方法可返回介于 0 ~ 1 之间的一个随机数。那么猜想在0~1之间,如果对生成的随机数进行四舍五入,那么该概率在(0,1)是呈均匀分布状态,也就是说出现0或者是1的概率是相等的,接下来验证猜想

function guess(){
    var zero = 0;
    var one = 0;
    for(var i=0;i<100000;i++){
        Math.round(Math.random()) ==1 ? one++ : zero++;
    }
    return zero+"  "+one;
}

for(var i=0;i<10;i++){
    var g = guess();
    console.log(g);
}

运行结果如下
50093  49907
49787  50213
49862  50138
49948  50052
49820  50180
50158  49842
50179  49821
49967  50033
49920  50080
50063  49937
从数据结果中可以看出,对随机数四舍五入之后,出现0和出现1的概率呈均匀分部状态,测试次数无穷大的情况下,那么出现1或0的概率的极限都是1/2,根据这个特性,由二进制开始联想,那么在指定位数的情况下,在这个区间内,每一个数出现的概率也是均匀分布的,概率各为1/2^n,于是就有了下面的验证程序如下

var Helpers = {
    getbit: function(num){
        var bit = 0;
        while(num>0){
            num = num>>1;
            bit++;
        }
        return bit;
    },
    randomBin : function(times){
        var num = Math.round(Math.random());
        while(times>1){
            num = (num<<1) + Math.round(Math.random());
            times--;
        }
        return num;
    },
    random : function(min,max){
        var num = max-min;
        var times = this.getbit(num);
        do{
            var binNum = this.randomBin(times);
        }while(!(binNum<=num));
        return binNum+min;
    }
}

var zero = one = two = three = 0;
for(var i=0; i<=10000; i++){
    var n = Helpers.random(0,3);
    if(n == 0){
        zero++;
    }else if(n == 1){
        one++;
    }else if(n == 2){
        two++;
    }else if(n == 3){
        three++;
    }
}
console.log(zero,one,two,three);

运行10000次的结果:2523 2548 2416 2514 ,根据数据可以看出,这种生成随机数的方式比之第一种要更加的均匀

尾语:

虽然复用代码是一个好习惯,但是不要盲目的去复用他人的代码,靠巧合编程是无法长久的,惟有不断的提升自己,才会觉得数学与计算机真的是非常的有趣。

vagrant学习笔记

什么是vagrant
简而言之,vagrant就是一个用来管理虚拟机文件的工具
为什么要使用vagra
如果经常玩虚拟机的话,就会知道,当你需要新建一个虚拟环境的时候,总是要重复的安装操作系统,以及操作系统必备的工具,如果每次新建虚拟环境都要重复这一过程,那将不仅是身体上的煎熬,还有思想上的绑架,所幸的是vagrant已经帮你搞定好了这一切,只要你拥有vagrant,git,VitualBox(or VMWare),就能轻松的接入vagrant

如何使用vagrant
在vagrant中,所有的虚拟机环境都应该被称之为box,当然你也可以叫做盒子,甚至叫包也无所谓,但目的是要理解这个box其实就是把所有的虚拟机中的文件进行了打包而已,所以当你决定要使用某种操作系统的时候,应该去选择对应的box,在vagrant中,下载box非常的简单,只需要一行命令就可以了,比如我需要安装个hashicorp/precise64的box,那么就用下面的命令

vagrant box add hashicorp/precise64

这个下载过程一般都要持续个几分钟,在此期间可以去小酌一杯咖啡
添加box之后,就需要进行初始化了,使用vagrant init hashicorp/precise64命令来初始化box

vagrant init hashicorp/precise64

接着直接vagrant up启动box,就会看到虚拟机已经启动precise64了

vagrant up

再接着就是vagrant ssh登陆到命令行管理界面,剩下的就是和linux操作系统终端一样了,非常的easy

vagrant ssh

 

vagrant还有什么功能
vagrant除了能够管理虚拟机之外,还有很多非常强大的功能,比如说目录映射,把虚拟机的某一个目录映射到宿主机上,可以让你在宿主机修改文件从而同步更新虚拟机中文件的效果,我觉得这个功能真的是非常的black,它能够让你在windows环境下开发,跑的却是linux的服务,同时具有服务器环境一致的属性绝对是团队开发的神器,省去了不断ftp代码然后测试的烦恼了。

作为程序员,偷懒是一种必备的品质,如果你也觉得vagrant不错的话,赶紧access to vagrant吧!

我的HTTPS升级之路

引子:

最近在一篇文章中了解到EFF(电子前哨基金会)为了推广https协议,成立了一个Let's encrypt项目,可以发放免费的证书,此证书可以被大多数主流浏览器所信任,于是就顺手给自己的网站弄了一个。

准备:
工具:certbot
环境:centOS7

获取Certbot工具:
根据我在网上了解到的信息,获取certbot工具有三种方法
第一种是通过git在github中下载

git clone https://github.com/certbot/certbot.git

第二种是通过epel-release软件源,这个软件源有许多yum中没有的软件包,包括certbot

yum install epel-release
yum install certbot

第三种是通过wget来进行下载

wget https://dl.eff.org/certbot-auto

由于钟爱github,熟悉git所以直接使用git下载好了
执行命令

git clone https://github.com/certbot/certbot.git

 

生成证书:
下载完了之后,会创建一个certbot的目录,然后使用certbot-auto工具来生成证书,如果certbot没有可执行权限,还需要执行命令chmod u+x certbot-auto

cd certbot
./certbot-auto certonly --standalone --email crisen@crisen.org  -d www.crisen.org

然后agree协议 静静等待生成证书即可
出现下面提示就说明安装好了

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
   /etc/letsencrypt/live/your.domain.com/fullchain.pem. Your cert
   will expire on 20XX-09-23. To obtain a new or tweaked version of
   this certificate in the future, simply run certbot again. To
   non-interactively renew *all* of your certificates, run "certbot
   renew"
 - If you like Certbot, please consider supporting our work by:

   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

一般来说证书会生成在/etc/letsencrypt/live目录下

部署证书:
接着把证书的公钥和私钥配置到nginx的ssl目录下,创建软链接

ln -s /etc/letsencrypt/live/www.crisen.org/fullchain.pem   /usr/local/nginx/conf/ssl/www.crisen.org.crt
ln -s /etc/letsencrypt/live/www.crisen.org/privkey.pem    /usr/local/nginx/conf/ssl/www.crisen.org.key

当然直接复制过去也是可行的

cp -i  /etc/letsencrypt/live/www.crisen.org/fullchain.pem  /usr/local/nginx/conf/ssl/www.crisen.org.crt
cp -i /etc/letsencrypt/live/www.crisen.org/privkey.pem  /usr/local/nginx/conf/ssl/www.crisen.org.key

接下来只要配置 nginx 的https服务就可以了 下面是我的nginx服务器配置文件 仅做参考

server {
    listen 80;
    listen 443 ssl http2;
    ssl_certificate /usr/local/nginx/conf/ssl/www.crisen.org.crt;
    ssl_certificate_key /usr/local/nginx/conf/ssl/www.crisen.org.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_timeout 10m;
    ssl_session_cache builtin:1000 shared:SSL:10m;
    ssl_buffer_size 1400;
    add_header Strict-Transport-Security max-age=15768000;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate   /usr/local/nginx/conf/ssl/www.crisen.org.crt;
    server_name www.crisen.org;
    access_log /data/wwwlogs/www.crisen.org_nginx.log combined;
    index index.html index.htm index.php;
    include /usr/local/nginx/conf/rewrite/none.conf;
    root /data/wwwroot/profiles;
    if ($ssl_protocol = "") { return 301 https://$host$request_uri; }

    location ~ [^/]\.php(/|$) {
        #fastcgi_pass remote_php_ip:9000;
        fastcgi_pass unix:/dev/shm/php-cgi.sock;
        fastcgi_index index.php;
        include fastcgi.conf;
        }
    location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|ico)$ {
        expires 30d;
        access_log off;
        }
    location ~ .*\.(js|css)?$ {
        expires 7d;
        access_log off;
    }
}
配置好之后重启nginx服务器

效果测试:
然后进入到www.crisen.org测试一下

出现了可信任的证书 到此配置完毕

踩过的坑:
服务器操作系统版本过低:
开始的时候我的操作系统是centOS5.1版本的,内置的python只有2.4,结果没有办法启动certbot出现,

因为certbot-auto是python写的,并且必须要2.6以上的版本才可以,

网上查看了许多文档,也确定了certbot只支持更加现代的操作系统
解决办法:备份网站数据,升级服务器操作系统

ps:互联网的技术是日新月异的,本文仅做参考用.

强大的程序员不一定是优秀的,但是优秀的程序员一定会变的很强大

1.Care about your craft  关心你的技艺
2.Think about your work  思考!你的工作
3.Provide options,don't make lame excuses  提出各种选择,不要找蹩脚的借口
4.don't live with broken wendows 不要容忍破窗户
5.be a catalyst for change 做变化的催化剂
6.remember the big picture 记住大图景
7.make quality a requirements issue 使质量成为需求问题
8.invest Regularly in your knowledge portfolio 定期为你的知识资产投资
9.critically analyze what you read and hear 批判性的分析你读到的和听到的
10.it's both what you say and the way you speak it 你说什么和你怎么说同样重要
11.Don't repeat yourself 不要重复自己
12.make it easy to reuse 让复用变的容易
13.eliminate effects between unrelated things 消除无关事物之间的影响
14.there no final decisions 不存在最终决策
15.use tracer bullets to find the target 只用曳光弹找到目标
16.prototype to learn 为了学习而制作原型
17.program close to the problem domain 靠近问题领域编程
18.estimate to avoid surprice 估算,避免发生意外
19.iterate the schedule with the code 通过代码对进度表进行迭代
20.keep knowledge in plain text 使用纯文本保存你的知识
21.use the power of command shells 利用shell命令力量
22.use a single editor well 用好一种编辑器
23.always use source code controll 总是使用源码控制
24.fix the problem not to blame 要修正问题,而不是发出指责
25.don not panic when debuging 不要恐慌
26.'select' isn't broken ‘select’没有问题
27.don't assume it,prove it 不要假定 要证明
28.learn a text manipulation language 学习一种文本操作语言
29.write code that write code 编写能写代码的代码
30.you can't write perfect software 你不可能写出完美的软件
31.design with contracts 通过合约进行设计
32.crash earlt 早崩溃
33.if it can't happen,use assertions to ensure that it won't 如果它不可能发生,用断言确保它不会发生
34.use exceptions for exceptional problems 将异常用于异常的问题
35.finish what you start 有始有终
36.minimize coupling between modules 使模块之间的耦合减至最少
37.configure,don't integrate 要配置 不要集成
38.put abstractions in code,details in metadata 将抽象放进代码,细节放进元数据
39.analyze workflow to improve concurrency 分析工作流以改善并发性
40.design useing service 用服务进行设计
41.always design for concurrency 总是为并发性进行设计
42.separate views for modules 使视图和模型分离
43.use blackboards to coordinate workflow 用黑板协调工作流
44.don't program by coincidence 不要靠巧合编程
45.estimate the order of your algorithms 估算算法的阶
46.test your estimates 测试你的估算
47.refactor early,refactor often 早重构,常重构
48.design to test 为测试而设计
49.test your software,or your users will 测试你的软件,否则你的用户就得测试
50.don't use wizard code you don't understand 不要使用你不理解的向导代码
51.don't gather requirements - dig for them 不要搜集需求,挖掘它们
52.work with a user to think like a user 与用户一同工作,像用户一样思考
53.abstracts live longer than details 抽象比细节活的更长久
54.use a project glossary 使用项目词汇表
55.don't think outside the box - find the box 不要在盒子外面思考,找到这个盒子
56.listen to nagging doubts - start when you're ready 倾听反复出现的疑虑,等你准备好再开始
57.some things are better done than described 有些事情实践比理论来的更好
58.don't be a slave to formal methods 不要做形式方法的奴隶
59.exoensive tools don't produce better designs 昂贵的工具不一定能做出更好的设计
60.organize around functionality,bot job functions 围绕功能进行组织,而不是围绕工作职务
61.don't use manual procedures 不要使用手工流程
62.test early,test often,test automatically 早测试 常测试 自动化测试
63.codeing ain't done till all the test run 要通过全部测试,编码才算完成
64.use saboteurs to test your testing 通过蓄意破坏来测试你的测试
65.test state coverage,not codeing coverage 测试状态覆盖 而不是代码覆盖
66.find bug once 一个bug只抓一次
67.treat English as just another programming language 把英语当作又一种编程语言
68.build document in,don't bolt it once 把文档建在版本中,不要拴在外面
69.gently exceed your users' exceptations  温和的超出用户的期望
70.sign your work 在你的作品上签名

----摘自《程序员的修炼--从小工到专家》

浅析HTTP协议

HTTP协议是什么

HTTP协议是一种网际层协议,HTTP协议是无状态的,HTTP协议对用户是透明的。

每一次HTTP请求都是一次事务,一个HTTP事务是由一条请求命令和一个响应结果组成的,HTTP通信的最基本单位是HTTP报文。

形象通俗的概念理解HTTP协议

其实我觉得HTTP请求就好像去商店(服务器)买东西(请求资源)一样,比如说我拿钱去商店,然后说要买瓶矿泉水,然后商店老板收钱之后把我的矿泉水交到我手里,这就是完成了一次交易,也就是一次HTTP事务。而买东西需要钱就是一个约定,也就是HTTP协议.

理想状态就是拿钱买东西,但是这个过程往往不会永远都那么顺利,总会有各种各样的意外情况。

1.马上放假了,为了准备我的冬眠计划,于是我准备储存一下要过冬的粮食,于是到到商店买了泡面五连包(?_?),给了十块钱,这是时候商店老板很尴尬的说了一句,HTTP 100 continue,不好意思,还差两块五-_-||,没办法,只能再掏出两块五拉,这个时候商店老板很高兴的说了一句HTTP 200 OK,拿好你的东西慢走啊!

2.最近商店决定装修了,门口贴出了一张告示(HTTP 302 Move temporarily),商店装修,临时移动到隔壁了,请到隔壁买东西,那没办法,东西还得买,过冬粮食不能少啊,结果没过两天,商店又贴出告示,(HTTP 301 Moved Permanently),装修花费的时间太长拉,以后就到隔壁买东西吧,好吧,以后就只到隔壁买拉(@_@)

3.商店推出了新的活动,有特价的机械炫酷版键鼠,我看着很心动,于是准备买下来,但是商店老板说:(HTTP 401 Unauthorized ),这是会员专属商品,得办会员卡才能买,好吧~为了买到我心爱的机械键鼠,办卡就办卡吧

刚好这个时候,隔壁的张三同学来了,这个人心眼比较坏,拿着一张20元的假币去买饮料,不巧的是商店老板慧眼如炬,直接就发现了,然后告诉他(HTTP 403 Forbidden),我们这不收假币(-_-||)

过了一段时间之后,我总感觉自己的电脑很慢,于是我琢磨着要换个好一点的CPU,不要太好的就用core i7 6700的cpu吧,然后我兴致勃勃的跑到商店,结果迎来一盆冷水:你要买的这个东西,暂时还没有货(HTTP 404 not found),好吧,等你们进货了记得告诉我(-_-||)

4.最近流感很严重,我准备到商店买感冒药(ps:万能的商店啊,什么都能买,就像机器猫的口袋一样),但是很不凑巧,商店老板也感冒了,门口特出了告示:(HTTP 500 Internal Server Error),老板生病了,暂不提供服务(-_-||),老板知道这件事情之后,他觉得这样会损失很多生意,于是招了个伙计(网关),然后老板只要收钱就行了,跑腿的事就让伙计去干,正巧我今天刚好下班回家,准备买点八宝粥回去吃,结果新来的伙计还没开始上班,老板只能无奈的说(502 bad gateway),伙计还没来,我感冒还没好,你过一个小时再来吧,过了一个小时,伙计来了,老板让他去仓库里拿那个银鹭的桂圆莲子八宝粥,伙计刚好第一天上班,找了半天没找着,我饿的实在不行了,老板只能很无奈的告诉我(HTTP 504 gateway timeout),新来的伙计不懂业务,你今天还是别吃这个了,弄点泡面吃吧(-_-|| 老板的都知道我爱吃泡面了)

因为店里什么都卖,所以店里的客户越来越多了,老板的精力有限,没有办法记得过来那么多熟人,起初为了让老板能够记住我这个吃泡面的常客,于是我告诉他,我住在你后面那栋楼(IP地址记忆),但是我转念一想,后面那栋楼可能不止我一个人啊,万一我要是搬家了呢,老板岂不是记不住我了-_-||,于是我用了一种比较笨的办法,把我的名字和住址贴到我的衣服上(胖url方式),这样老板每次一看纸条就能知道我是谁了。但是感受到无数人异样的眼光之后,我觉得有必要和商店老板商量一下了,就采用办会员卡(session)的形式来记住那些常客吧,让他们登记一下姓名和电话之后,给他们发一张卡(sessionid),然后每次来只要刷一下卡,就能立刻认出是谁拉。老板听了我的仔细分析之后,觉得这个方法非常好,于是就采用了这种方式来记住客户。后来每次买东西,我只要从口袋(cookie)里掏出我的会员卡刷一下,老板就能立刻知道我是谁了(老板比较健忘,我买了那么多泡面,都记不住我-_-||)

理想是好的,但是老板发现,并不是所有的人都有口袋(客户端禁用cookie),就比如说我楼下的小花,每天都是穿裙子,根本没有口袋啊,那就只能拿在手里拉(把session放在隐藏域表单),或者是挂在自己的脖子上(sessionid放在url中),这样老板就能记住拉,但是直接暴露在别人的视线下,太不安全拉,毕竟财不外漏嘛,虽然放在口袋里,也有被人顺走的情况(cookie劫持),但比放手上要好点吧,果不其然,隔壁的张三同学就使坏,把小花的会员卡(sessionid)给顺手牵羊了,然后直接拿着会员卡去买东西了(跨站请求伪造csrf),但是老板记性不好,只要有卡就行,至于拿卡的是不是本人,那他就管不着了。老板记性很差,这也是没有办法的事情,只能提醒一下各位,请保管好自己的会员卡,老板只认卡不认人(-_-||)

虽然老板记性不是很好,但是为人踏实敬业,随着他的努力,客户越来越多了,这个时候一家店就忙不过来了,于是老板决定开分店(服务器集群,负载均衡),但是分店开起来之后,我发现我在这里办的会员卡在那边分店居然不能使用,这我就不能忍了,为什么都是你开的店,这边的会员卡那边不能用呢(?_?),于是我只能跟老板说,既然都是会员,那么这个会员卡必须是两边都能刷的(seesion共享),不然客户肯定不满意对吧,老板听了我分析之后,决定专门设立一处管理会员卡的地方(session服务器),这样买完东西直接到专门刷卡的地方去就好了。采用了这样的方法之后,办卡的人就越来越多了,为了方便大家刷卡,只能多搞几个会员卡卡管理处了(session集群),这样的话差不多就没有什么大问题了。不过分店开了,会员卡也管理好了,但是这个货物渠道出了点问题,买东西的人太多,一个仓库的货物已经不够用了啊,只能多搞几个仓库拉(分库),水果就专门放水果仓库,蔬菜就专门蔬菜的仓库,零食就弄零食仓库拉,但是水果里面,西瓜进的太多了,没有办法,西瓜多搞点空地放吧(分表),这样管理就差不多了。

看到商场越来越大,我觉得很欣慰。恰好又是要过冬的时候了,该储备粮食拉,我拿着会员卡说买个五连包,但是零食卖的太快了,商店的柜台上(缓存)没有了,然后老板让伙计(网关)去仓库拿一些过来,伙计按照老板的吩咐来到了仓库,发现仓库正在进货(表级锁定),不让取货物,这个可把我等坏了,我不就买了泡面么,居然等了几个小时,时间再长一点,我都要饿死了(?_?),这样很明显是不对的吧,我只能再次的给老板建议拉,你这个进货和拿货应该分开来弄(读写分离),弄一个仓库专门进货,另一个仓库专门拿货比较好(主从配置),然后让这个拿货的仓库安排一个专门的工作人员,把新进的货物运到这个仓库来就好了啊,这样就不会存在让客户等好长时间了。健忘的老板果断的采用了这一建议,看着我买泡面的地方,一步步的成长到这个高度,我感觉非常的欣慰,我决定了,以后吃泡面就认准这家店了,其他地方哪都不去(@_@)