co最简版实现,学习generator & co
看了co的源码 比较难懂 了解了其原理后实现了一个最简版本https://github.com/yucong/simple-co 希望对想学习的tx有帮助~ yeild后面只支持thunk,co本身也是一个thunk 核心代码:
- function co(generator) {
- return function(fn) {
- var gen = generator();
- function next(err, result) {
- if(err){
- return fn(err);
- }
- var step = gen.next(result);
- if (!step.done) {
- step.value(next);
- } else {
- fn(null, step.value);
- }
- }
- next();
- }
- }
用法:
- var co = require('./co');
- // wrap the function to thunk
- function readFile(filename) {
- return function(callback) {
- require('fs').readFile(filename, 'utf8', callback);
- };
- }
- co(function * () {
- var file1 = yield readFile('./file/a.txt');
- var file2 = yield readFile('./file/b.txt');
- console.log(file1);
- console.log(file2);
- return 'done';
- })(function(err, result) {
- console.log(result)
- });
会打印出: content in a.txt content in b.txt done
下面做个简单对比:
传统方式,sayhello
是一个异步函数,执行helloworld
会先输出"world"
再输出"hello"
。
- function sayhello() {
- return Promise.resolve('hello').then(function(hello) {
- console.log(hello);
- });
- }
- function helloworld() {
- sayhello();
- console.log('world');
- }
- helloworld();
输出
- > "world"
- > "hello"
co 的方式,会先输出"hello"
再输出"world"
。
- function co(gen) {
- var it = gen();
- var ret = it.next();
- ret.value.then(function(res) {
- it.next(res);
- });
- }
- function sayhello() {
- return Promise.resolve('hello').then(function(hello) {
- console.log(hello);
- });
- }
- co(function *helloworld() {
- yield sayhello();
- console.log('world');
- });
输出
- > "hello"
- > "world"
消除回调金字塔
假设sayhello
/sayworld
/saybye
是三个异步函数,用真正的 co 模块就可以这么写:
- var co = require('co');
- co(function *() {
- yield sayhello();
- yield sayworld();
- yield saybye();
- });
输出
- > "hello"
- > "world"
- > "bye"
vmware 4.1版本物理机部署6.0版本OVF模板 报“硬件系列vmx-11不受支持“的解决办法
问题背景,从vmware6.0版本的物理机上导出虚拟机ovf模板后,导入到4.1版本物理机上时报错:“硬件系列vmx-11不受支持”。
1.打开xxx.ovf文件,将<vssd:VirtualSystemType>vmx-11</vssd:VirtualSystemType> 改成物理机支持的版本:<vssd:VirtualSystemType>vmx-7</vssd:VirtualSystemType>
2.打开xxx.mf文件,将对VOF引用的哪一行删掉,不然 在部署的时候会报文件 xxxx.ovf 的完整性检查失败,可能在传输过程中已损坏。
删掉 SHA1(xxx.ovf)= f801b24cd5f664a9f3f88810b87e0080fb5bf29f
google chrome 插件安装目录
MAC:
- /Users/jesse/Library/Application Support/Google/Chrome/Default/Extensions/nhdogjmejiglipccpnnnanhbledajbpd/0.0.2_0
windows:
- C:\Users\Administrator\AppData\Local\Google\Chrome\User Data\Default\Extensions\nhdogjmejiglipccpnnnanhbledajbpd\3.1.4_0
Docker v17.04.0-ce-rc1 发布,应用容器引擎
Docker v17.04.0-ce-rc1 发布了,并将于 2017-04-05 发布 17.04.0-ce 版本。本次更新内容如下:
Client
Suppressing image digest in docker ps #30848
Hide command options that are related to Windows #30788
Fix docker plugin install prompt to accept "enter" for the "N" default #30769
Add truncate function for Go templates #30484
Support expanded syntax of ports in stack deploy #30476
Support expanded syntax of mounts in stack deploy #30597 #31795
Add --add-host for docker build #30383
Add .CreatedAt placeholder for docker network ls --format #29900
Add --filter enabled=true for docker plugin ls #28627
Add --format to docker service ls #28199
Add publish and expose filter for docker ps --filter #27557
Support multiple service IDs on docker service ps #25234
Allow swarm join with --availability=drain #24993
Removal of the email from docker login #26868
Networking
Check parameter --ip, --ip6 and --link-local-ip in docker network connect #30807
Added support for dns-search #30117
Added --verbose option for docker network inspect to show task details from all swarm nodes #31710
Clear stale datapath encryption states when joining the cluster docker/libnetwork#1354
Ensure iptables initialization only happens once docker/libnetwork#1676
Fix bad order of iptables filter rules docker/libnetwork#961
Add anonymous container alias to service record on attachable network docker/libnetwork#1651
Support for com.docker.network.container_interface_prefix driver label docker/libnetwork#1667
Runtime
Handle paused container when restoring without live-restore set #31704
Do not allow sub second in healthcheck options in Dockerfile #31177
Support name and id prefix in secret update #30856
Use binary frame for websocket attach endpoint #30460
Fix linux mount calls not applying propagation type changes #30416
Fix ExecIds leak on failed exec -i #30340
Prune named but untagged images if danglingOnly=true #30330
Add daemon flag to set no_new_priv as default for unprivileged containers #29984
Add daemon option --default-shm-size #29692
Support registry mirror config reload #29650
Ignore the daemon log config when building images #29552
Move secret name or ID prefix resolving from client to daemon #29218
Implement optional ring buffer for container logs #28762
Allow adding rules to cgroup devices.allow on container create/run #22563
Swarm Mode
Topology-aware scheduling #30725
Automatic service rollback on failure #31108
Worker and manager on the same node are now connected through a UNIX socket docker/swarmkit#1828, docker/swarmkit#1850, docker/swarmkit#1851
Improve raft transport package docker/swarmkit#1748
No automatic manager shutdown on demotion/removal docker/swarmkit#1829
Use TransferLeadership to make leader demotion safer docker/swarmkit#1939
Decrease default monitoring period docker/swarmkit#1967
Add Service logs formatting #31672
Fix service logs API to be able to specify stream #31313
Add --stop-signal for service create and service update #30754
Add --read-only for service create and service update #30162
Renew the context after communicating with the registry #31586
Windows
Wait for OOBE to prevent crashing during host update #31054
Block pulling Windows images on non-Windows daemons #29001
下载
deb/rpm install: curl -fsSL https://test.docker.com/ | sh
Linux 64bits tgz: https://test.docker.com/builds/Linux/x86_64/docker-17.04.0-ce-rc1.tgz
Darwin/OSX 64bits client tgz: https://test.docker.com/builds/Darwin/x86_64/docker-17.04.0-ce-rc1.tgz
Linux 32bits arm tgz: https://test.docker.com/builds/Linux/armel/docker-17.04.0-ce-rc1.tgz
Windows 64bits zip: https://test.docker.com/builds/Windows/x86_64/docker-17.04.0-ce-rc1.zip
Windows 32bits client zip: https://test.docker.com/builds/Windows/i386/docker-17.04.0-ce-rc1.zip
What does el5, el6, and el7 mean?
EL is short for Red Hat Enterprise Linux (EL).
EL6 is the download for Red Hat 6.x, CentOS 6.x, and CloudLinux 6.x.
EL5 is the download for Red Hat 5.x, CentOS 5.x, CloudLinux 5.x.
EL7 is the download for Red Hat 7.x, CentOS 7.x, and CloudLinux 7.x.
The UNIXy Varnish Plugins run on all the above platforms.
RC ?
RC=Release Candidate,含义是”发布候选版”,它不是最终的版本,而是最终版(RTM=Release To Manufacture)之前的最后一个版本。广义上对测试有三个传统的称呼:alpha、beta、gamma,用来标识测试的阶段和范围。alpha 是指内测,即现在说的CB,指开发团队内部测试的版本或者有限用户体验测试版本。beta 是指公测,即针对所有用户公开的测试版本。然后做过一些修改,成为正式发布的候选版本时叫做gamma,现在叫做RC(Release Candidate)。
官网tar.gz下载:https://download.docker.com/linux/static/stable/x86_64/
官网安装教程:https://docs.docker.com/engine/installation/linux/centos/#install-from-a-package
下载
Docker重大更新,2017-03-02版本升至17.03,包名仓库全换
3月2日,Docker 官方发布了一篇 blog ,宣布企业版到来。版本也从1.13.x一跃到17.03。
之后,Docker 会每月发布一个 edge 版本(17.03, 17.04, 17.05...),每三个月发布一个 stable 版本(17.03, 17.06, 17.09...),企业版(EE) 和 stable 版本号保持一致,但每个版本提供一年维护。
Docker 的 Linux 发行版的软件仓库也从以前的https://apt.dockerproject.org / https://yum.dockerproject.org 变更为目前的 https://download.docker.com/。软件包名变更为 docker-ce(社区版) 和 docker-ee(企业版)。
旧的仓库和包名(docker-engine)依旧可以使用,但不确定什么时候会被废弃,docker-engine 的版本号也变成了17.03.0~ce-0这种的版本号。
Docker v17.03.0-ce 版本更新内容和下载地址请查看发行日志。
Docker的网络模式和跨主机通信(Docker的四种网络模式Bridge模式)
当Docker进程启动时,会在主机上创建一个名为docker0...
Docker的四种网络模式
1. Bridge模式
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器会连接到这个虚拟网桥上。虚拟网桥的工作方式和物理交换机类似,这样主机上的所有容器就通过交换机连在了一个二层网络中。
从docker0子网中分配一个IP给容器使用,并设置docker0的IP地址为容器的默认网关。在主机上创建一对虚拟网卡veth pair设备,Docker将veth pair设备的一端放在新创建的容器中,并命名为eth0(容器的网卡),另一端放在主机中,以vethxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。可以通过brctl show命令查看。
bridge模式是docker的默认网络模式,不写--net参数,就是bridge模式。使用docker run -p时,docker实际是在iptables做了DNAT规则,实现端口转发功能。可以使用iptables -t nat -vnL查看。
bridge模式如下图所示:
- #docker run -tid --net=bridge --name docker_bri1 ubuntu-base:v3
- #docker run -tid --net=bridge --name docker_bri2 ubuntu-base:v3
- #brctl show
- #docker exec -ti docker_bri1 /bin/bash
- #docker exec -ti docker_bri1 /bin/bash
- #ifconfig –a
- #route –n
2. Host模式
如果启动容器的时候使用host模式,那么这个容器将不会获得一个独立的Network Namespace,而是和宿主机共用一个Network Namespace。容器将不会虚拟出自己的网卡,配置自己的IP等,而是使用宿主机的IP和端口。但是,容器的其他方面,如文件系统、进程列表等还是和宿主机隔离的。
Host模式如下图所示:
演示:
- #docker run -tid --net=host --name docker_host1 ubuntu-base:v3
- #docker run -tid --net=host --name docker_host2 ubuntu-base:v3
- #docker exec -ti docker_host1 /bin/bash
- #docker exec -ti docker_host1 /bin/bash
- #ifconfig –a
- #route –n
3. Container模式
这个模式指定新创建的容器和已经存在的一个容器共享一个 Network Namespace,而不是和宿主机共享。新创建的容器不会创建自己的网卡,配置自己的 IP,而是和一个指定的容器共享 IP、端口范围等。同样,两个容器除了网络方面,其他的如文件系统、进程列表等还是隔离的。两个容器的进程可以通过 lo 网卡设备通信。
Container模式示意图:
演示:
- #docker run -tid --net=container:docker_bri1 --name docker_con1 ubuntu-base:v3
- #docker exec -ti docker_con1 /bin/bash
- #docker exec -ti docker_bri1 /bin/bash
- #ifconfig –a
- #route -n
4. None模式
使用none模式,Docker容器拥有自己的Network Namespace,但是,并不为Docker容器进行任何网络配置。也就是说,这个Docker容器没有网卡、IP、路由等信息。需要我们自己为Docker容器添加网卡、配置IP等。
Node模式示意图:
演示:
- #docker run -tid --net=none --name docker_non1 ubuntu-base:v3
- #docker exec -ti docker_non1 /bin/bash
- #ifconfig –a
- #route -n
跨主机通信
Docker默认的网络环境下,单台主机上的Docker容器可以通过docker0网桥直接通信,而不同主机上的Docker容器之间只能通过在主机上做端口映射进行通信。这种端口映射方式对很多集群应用来说极不方便。如果能让Docker容器之间直接使用自己的IP地址进行通信,会解决很多问题。按实现原理可分别直接路由方式、桥接方式(如pipework)、Overlay隧道方式(如flannel、ovs+gre)等。
直接路由
通过在Docker主机上添加静态路由实现跨宿主机通信:
Pipework
Pipework是一个简单易用的Docker容器网络配置工具。由200多行shell脚本实现。通过使用ip、brctl、ovs-vsctl等命令来为Docker容器配置自定义的网桥、网卡、路由等。
使用新建的bri0网桥代替缺省的docker0网桥
bri0网桥与缺省的docker0网桥的区别:bri0和主机eth0之间是veth pair
Webbench MAC下安装
Webbench是有名的网站压力测试工具,它是由 Lionbridge公司开发。
Webbech能测试处在相同硬件上,不同服务的性能以及不同硬件上同一个服务的运行状况。webBech的标准测试可以向我们展示服务器的两项内容:每秒钟相应请求数和每秒钟传输数据量。webbench不但能具有便准静态页面的测试能力,还能对动态页面(ASP,PHP,Java,CGI)进 行测试的能力。还有就是他支持对含有SSL的安全网站例如电子商务网站进行静态或动态的性能测试。
安装: Make install 需 sudo 权限, 需要写入 /usr/local/bin
- brew install ctags # 依赖安装
- curl -o webbench.tar.gz http://blog.zyan.cc/soft/linux/webbench/webbench-1.5.tar.gz
- tar -zxvf webbench-1.5.tar.gz
- cd webbench-1.5/
- mkdir -pv /usr/local/man/man1 # 关键
- sudo make && sudo make install # sudo 权限因为需要创建文件夹
Mac下自带apache压力测试:
- localhost:webbench-1.5 jesse$ webbench -c 500 -t 120 http://localhost/
- Webbench - Simple Web Benchmark 1.5
- Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
- Benchmarking: GET http://localhost/
- 500 clients, running 120 sec.
- Speed=33001 pages/min, 696314 bytes/sec.
- Requests: 64078 susceed, 1924 failed.
- localhost:webbench-1.5 jesse$
实例化php类的时候如何传参
当我们实例化一个php类的时候,要怎么传递参数呢?这取决于该类的构造方法。
例:
person.class.php
class person{
var $name;
var $color;
var $sex;
var $age;
function __construct($name,$age='',$sex='boy'){
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
$this->color = 'yello';
}
function eat(){
echo $this->name.'要吃饭';
}
function xinxi(){
echo $this->name.' is '.$this->sex.' and age is '.$this->age.' fuse is '.$this->color;
}
}
?>
son.php
include('person.class.php');
$son = new person('cuihua',25,'girl');//此处的参数传递要和类的构造方法里面的参数顺序对应
//$son->xinxi();//cuihua is girl and age is 25 fuse is yello
$son->name = '田妞';
$son->eat();//田妞要吃饭
?>
搞定 koa 之generator 与 co
koa 是由 tj大神利用 generator 开发的 web 框架。要理解 koa,首先要先了解 generator 与 co。作为搞定 koa 的第一篇,我们便谈谈这个。文章首发在boke.io
generator介绍
function* Gene(){
yield 1;
yield 2;
}
var gene = Gene();
console.log(gene.next());//{ value: 1, done: false }
console.log(gene.next());//{ value: 2, done: false }
console.log(gene.next());//{ value: undefined, done: true }
console.log(gene.next());//Error: Generator has already finished 经@Ralph-Wang提醒从 v0.11.13 开始不抛错了,返回{ value: undefined, done: true }
从上面我们可以看到
generator 的定义和函数类似,只是在 function 后面多了一个*
调用generator 和调用函数一样,只是不像函数立即执行,而是会生成一个对象
generator 生成的对象存在一个 next 函数,调用 next 会返回 yield运算的结果对象,并停止。再次调用会在下一个 yield 处停止。
当所有的 yield 被执行完,调用 next 函数会返回{ value: undefined, done: true }。再次调用会报错
generator 与异步
看完 generator 的介绍,你心里回想这跟异步有毛关系?不着急听我接着说
串行请求两个网页的代码
var request = require('request');
var a = {};
var b = {};
request('http://www.google.com', function (error, response, body) {
if (!error && response.statusCode == 200) {
a.response = response;
a.body = body;
request('http://www.yahoo.com', function (error, response, body) {
if (!error && response.statusCode == 200) {
b.response = response;
b.body = body;
}
});
}
});
我们再看看最终我们是如何利用 generator请求网页的
co(function *(){
var a = yield request('http://google.com');
var b = yield request('http://yahoo.com');
console.log(a[0].statusCode);
console.log(b[0].statusCode);
})()
上面的代码可以看到,co 里面传入了一个 generator,里面用 yield 调用异步函数。从逻辑上看,里面的异步被变成了同步。
co 到底有什么魔法?可以把我们从异步中解救出来?
想想 generator 的特性,当我们执行第一个 next 的时候,会调用第一个 request,此时我们去调用 request 的逻辑,然后把 generator 的实例穿进去。当第一个 request 逻辑完成时,在调用这个 generator 的 next,这样就到了第二个 yield 的逻辑了。当然这需要一些逻辑的封装,也就是 co 了。
根据上面的分析,我们大概可以写出下面的代码
function co(Gene){
//先实例化一下
var gene = Gene();
//如果存在 next 函数
if(gene.next){
var fun = gene.next();//把异步函数返回过来,好继续封装
//fun 处理完,再调用 gene.next()
//...
}
}
从上面的代码可以看出
yield 后面的内容需要返回一个异步函数,这样我们才可进一步封装异步处理的逻辑。
fun 需要可以传入参数,这样才可以处理多个异步
需要一个递归调用,这样才可以持续调用 next,同时根据 next 返回对象中的done属性停止逻辑
需要考虑错误处理
今天就到这里,下一篇详细讲一下 co 的源码
co最简版实现,学习generator & co
看了co的源码 比较难懂 了解了其原理后实现了一个最简版本https://github.com/yucong/simple-co 希望对想学习的tx有帮助~ yeild后面只支持thunk,co本身也是一个thunk
核心代码:
function co(generator) {
return function(fn) {
var gen = generator();
function next(err, result) {
if(err){
return fn(err);
}
var step = gen.next(result);
if (!step.done) {
step.value(next);
} else {
fn(null, step.value);
}
}
next();
}
}
用法:
var co = require('./co');
// wrap the function to thunk
function readFile(filename) {
return function(callback) {
require('fs').readFile(filename, 'utf8', callback);
};
}
co(function * () {
var file1 = yield readFile('./file/a.txt');
var file2 = yield readFile('./file/b.txt');
console.log(file1);
console.log(file2);
return 'done';
})(function(err, result) {
console.log(result)
});
会打印出:
content in a.txt
content in b.txt
done
================================
generator_co: http://liuxinxiu.com/generator_co/