正则表达式

今天在 使用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集群),这样的话差不多就没有什么大问题了。不过分店开了,会员卡也管理好了,但是这个货物渠道出了点问题,买东西的人太多,一个仓库的货物已经不够用了啊,只能多搞几个仓库拉(分库),水果就专门放水果仓库,蔬菜就专门蔬菜的仓库,零食就弄零食仓库拉,但是水果里面,西瓜进的太多了,没有办法,西瓜多搞点空地放吧(分表),这样管理就差不多了。

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

浅谈session&cookie

session&cookie的出现

众所周知,HTTP协议是一种无状态的协议,当次请求下一次请求没有任何的关联,所以单纯的用HTTP来记住用户信息是行不通的。每次点击一个链接都需要需要输入用户名和密码的感觉是一种怎样的酸爽体验,为了展现用户的友好性,于是聪明(lan duo)的程序员们就想到了session这种解决方案来保存用户信息。

session是什么

  其实session没有多神奇的地方,只是保存在服务器的一小段数据而已,然后生成一个唯一标识,记作sessionid,然后把这个sessionid发送给用户,这样每次用户请求的时候只要带着这个sessionid,服务器就能知道这个用户的身份了。

cookie是什么

  cookie和session类似,只不过cookie保存在客户端,是以字符串的形式保存的,每次发送http请求的时候,都会把cookie放在请求的首部中,服务器可以通过解析首部从而得到cookie数据,从而得到用户信息,但是由于每次传输cookie需要消耗一定的带宽,所以为了节省资源,程序员们没有把所有的信息都保存在cookie中,而是生成了一个用来记录用户所有信息的id存放在cookie中

session&cookie的生命周期

  如果没有设置生命周期,那么session和cookie的数据是保存在内存中的,随着浏览器的关闭,所有的数据都会丢失,但是如果设置了生命周期,那么在生命周期的时间内,不主动的释放session的话,session会非常顽固的一直存在服务器中,采用这一特性有时候可以进行关键字的记录

用通俗的概念理解session&cookie

  假设服务器是一个大型的商场,用户每次请求就相当于一次购物,那么用户每次购物都需要把私人物品存放在存包处的柜子(session),然后用户会得到一个钥匙(sessionid),通常情况下,用户会把钥匙放在口袋中(cookie),每次购物结束,只需要拿着钥匙直接开启柜子(session)直接拿走自己的个人物品,那么就结束购物了。

但是实际情况总会有些偏差,假设今天客户是个妹子,穿的是裙子来没有口袋怎么办(客户端禁用了cookie),那么柜台人员只能告诉她你最好把钥匙放在手上(把sessionid放在表单的隐藏域中)或者直接带在脖子上(把sessionid放在url中)

钥匙放在手上或者口袋里,总有可能被有心人利用,偷到了钥匙,把客户的私人物品给顺手牵羊了(CSRF跨站请求伪造),这样肯定会给用户造成一定的损失,虽然可以通过让管理处的管理人员记住客户的长相(IP地址),但是还是没办法完全保证数据的安全性

有些时候商场也会造贼,柜子的锁被翘了(session丢失),给客户造成了相当严重的损失,所以为了避免这种情况,存包处的柜子一定要放在安全的地方并且有专人看守(seesion持久化).

商场经过这一系列的优化操作之后,开了分店了(负载均衡),这个时候如果客户来买东西,只把私人物品存到其中一个商场的话,逛完分店的时候还得回到原来的地方拿东西,肯定会给客户造成相当严重的困扰,于是聪明的商场管理人员就想到了一个折衷的解决方案,在两个商场之间设立了一个专门存放私人物品的地方(服务器集群,session共享),存完东西之后你可以任意的选择一个商场进行购物,买完东西只需要去专门管理私人物品的地方拿回自己的东西就好了