<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">今天要完成:</span>

1. nova api是如何创建wsgi服务的?为什么一个.../v2/{tanent_id}/server/{server_id}的处理方法和.../v2/​{tenant_id}​/servers/​{server_id}​/metadata的处理方法就不一样呢?

2. nova api到底监听了几个端口,有几个wsgi服务?

现象:

[root@compute-57-09 admin]# ps -ef|grep nova
root     10298 10105  1 Sep09 pts/6    07:28:09 /usr/bin/python /usr/bin/nova-api
root     10333 10116  0 Sep09 pts/17   00:23:36 /usr/bin/python /usr/bin/nova-consoleauth --config-file /etc/nova/nova.conf
root     10338 10113  0 Sep09 pts/14   00:23:00 /usr/bin/python /usr/bin/nova-cert --config-file /etc/nova/nova.conf
root     10339 10114  0 Sep09 pts/15   00:30:05 /usr/bin/python /usr/bin/nova-scheduler --config-file /etc/nova/nova.conf
root     10344 10117  0 Sep09 pts/18   00:00:04 /usr/bin/python /usr/bin/nova-objectstore --config-file /etc/nova/nova.conf
root     10346 10115  0 Sep09 pts/16   00:16:25 /usr/bin/python /usr/bin/nova-novncproxy --config-file /etc/nova/nova.conf --web /opt/stack/noVNC
root     10347 10112  1 Sep09 pts/13   07:20:57 /usr/bin/python /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
root     10628 10347  1 Sep09 pts/13   12:40:59 /usr/bin/python /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
root     10629 10347  1 Sep09 pts/13   12:40:49 /usr/bin/python /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
root     10630 10347  1 Sep09 pts/13   12:40:41 /usr/bin/python /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
root     10631 10347  1 Sep09 pts/13   12:41:08 /usr/bin/python /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
root     10632 10298  0 Sep09 pts/6    00:00:02 /usr/bin/python /usr/bin/nova-api
root     10633 10298  0 Sep09 pts/6    00:00:02 /usr/bin/python /usr/bin/nova-api
root     10634 10298  0 Sep09 pts/6    00:00:02 /usr/bin/python /usr/bin/nova-api
root     10635 10298  0 Sep09 pts/6    00:00:02 /usr/bin/python /usr/bin/nova-api
root     10658 10298  0 Sep09 pts/6    00:40:07 /usr/bin/python /usr/bin/nova-api
root     10659 10298  0 Sep09 pts/6    00:41:20 /usr/bin/python /usr/bin/nova-api
root     10660 10298  0 Sep09 pts/6    00:52:23 /usr/bin/python /usr/bin/nova-api
root     10661 10298  0 Sep09 pts/6    00:45:19 /usr/bin/python /usr/bin/nova-api
root     10666 10298  0 Sep09 pts/6    00:00:06 /usr/bin/python /usr/bin/nova-api
root     10667 10298  0 Sep09 pts/6    00:00:09 /usr/bin/python /usr/bin/nova-api
root     10668 10298  0 Sep09 pts/6    00:00:10 /usr/bin/python /usr/bin/nova-api
root     10669 10298  0 Sep09 pts/6    00:00:08 /usr/bin/python /usr/bin/nova-api
root     24157 10346  0 Oct08 pts/16   00:00:00 [nova-novncproxy] <defunct>
root     24499 17151  0 09:40 pts/0    00:00:00 grep nova

说明,nova-api很多,但是有一个父进程,就是最上面的那个,其他都是它派生出来的;

[root@compute-57-09 admin]# cat /usr/bin/nova-api
#!/usr/bin/python
# PBR Generated from u'console_scripts'
import sysfrom nova.cmd.api import mainif __name__ == "__main__":sys.exit(main())

nova.cmd.api的代码如下:

def main():config.parse_args(sys.argv)logging.setup("nova")utils.monkey_patch()objects.register_all()gmr.TextGuruMeditation.setup_autorun(version)launcher = service.process_launcher()for api in CONF.enabled_apis:should_use_ssl = api in CONF.enabled_ssl_apisif api == 'ec2':server = service.WSGIService(api, use_ssl=should_use_ssl,max_url_len=16384)else:server = service.WSGIService(api, use_ssl=should_use_ssl)launcher.launch_service(server, workers=server.workers or 1)launcher.wait()

1)是否nova-api一启动就是那多么个进程?

应该是的,我停止nova-api服务,又启动服务;发现直接多了好多

stack      781 11718 14 09:48 pts/7    00:00:03 /usr/bin/python /usr/bin/nova-api
stack      790   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api
stack      791   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api
stack      792   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api
stack      793   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api
stack      797   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api
stack      798   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api
stack      799   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api
stack      800   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api
stack      807   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api
stack      808   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api
stack      809   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api
stack      810   781  0 09:48 pts/7    00:00:00 /usr/bin/python /usr/bin/nova-api

a)会不会执行一条nova命令就会多出来一个nova-api 呢?

通过实验并没有多出来一个!说明,每个nova-api都各司其职,执行不同的代码。

b)如何知道每个nova-api监听的端口?

[root@compute-57-09 admin]# ps -ef|grep nova
root      8960 17151  0 10:05 pts/0    00:00:00 grep nova
root     10298 10105  1 Sep09 pts/6    07:28:26 /usr/bin/python /usr/bin/nova-api
root     10333 10116  0 Sep09 pts/17   00:23:36 /usr/bin/python /usr/bin/nova-consoleauth --config-file /etc/nova/nova.conf
root     10338 10113  0 Sep09 pts/14   00:23:01 /usr/bin/python /usr/bin/nova-cert --config-file /etc/nova/nova.conf
root     10339 10114  0 Sep09 pts/15   00:30:06 /usr/bin/python /usr/bin/nova-scheduler --config-file /etc/nova/nova.conf
root     10344 10117  0 Sep09 pts/18   00:00:04 /usr/bin/python /usr/bin/nova-objectstore --config-file /etc/nova/nova.conf
root     10346 10115  0 Sep09 pts/16   00:16:26 /usr/bin/python /usr/bin/nova-novncproxy --config-file /etc/nova/nova.conf --web /opt/stack/noVNC
root     10347 10112  1 Sep09 pts/13   07:21:13 /usr/bin/python /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
root     10628 10347  1 Sep09 pts/13   12:41:26 /usr/bin/python /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
root     10629 10347  1 Sep09 pts/13   12:41:16 /usr/bin/python /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
root     10630 10347  1 Sep09 pts/13   12:41:08 /usr/bin/python /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
root     10631 10347  1 Sep09 pts/13   12:41:35 /usr/bin/python /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
root     10632 10298  0 Sep09 pts/6    00:00:02 /usr/bin/python /usr/bin/nova-api
root     10633 10298  0 Sep09 pts/6    00:00:02 /usr/bin/python /usr/bin/nova-api
root     10634 10298  0 Sep09 pts/6    00:00:02 /usr/bin/python /usr/bin/nova-api
root     10635 10298  0 Sep09 pts/6    00:00:02 /usr/bin/python /usr/bin/nova-api
root     10658 10298  0 Sep09 pts/6    00:40:07 /usr/bin/python /usr/bin/nova-api
root     10659 10298  0 Sep09 pts/6    00:41:20 /usr/bin/python /usr/bin/nova-api
root     10660 10298  0 Sep09 pts/6    00:52:23 /usr/bin/python /usr/bin/nova-api
root     10661 10298  0 Sep09 pts/6    00:45:20 /usr/bin/python /usr/bin/nova-api
root     10666 10298  0 Sep09 pts/6    00:00:06 /usr/bin/python /usr/bin/nova-api
root     10667 10298  0 Sep09 pts/6    00:00:09 /usr/bin/python /usr/bin/nova-api
root     10668 10298  0 Sep09 pts/6    00:00:10 /usr/bin/python /usr/bin/nova-api
root     10669 10298  0 Sep09 pts/6    00:00:08 /usr/bin/python /usr/bin/nova-api
root     24157 10346  0 Oct08 pts/16   00:00:00 [nova-novncproxy] <defunct>
[root@compute-57-09 admin]# netstat -anlp  | grep 10298
tcp        0      0 0.0.0.0:8773                0.0.0.0:*                   LISTEN      10298/python
tcp        0      0 0.0.0.0:8774                0.0.0.0:*                   LISTEN      10298/python
tcp        0      0 0.0.0.0:8775                0.0.0.0:*                   LISTEN      10298/python 

看看8773 8774 8775都是干什么的?

网上说的很清楚:Nova-api 8773 (for EC2 API) 8774 (for openstack API) 8775 (metadata port) cinder 8776

[root@compute-57-09 admin]# netstat -anp  | grep 10632
[root@compute-57-09 admin]# netstat -anp  | grep 10633
[root@compute-57-09 admin]# netstat -anp  | grep 10634
[root@compute-57-09 admin]# netstat -anp  | grep 10635
[root@compute-57-09 admin]# netstat -anp  | grep 10658
tcp        0      0 192.168.39.30:8774          172.16.207.68:60072         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:55861         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:56512         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52688         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:60042         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:51513         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:51742         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:56662         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52576         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:51940         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52694         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:53572         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:56622         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:58098         192.168.39.30:5672          ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:56688         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52813         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:55874         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:56692         ESTABLISHED 10658/python
tcp        1      0 192.168.39.30:43471         192.168.39.190:3306         CLOSE_WAIT  10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:56652         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52792         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52554         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52786         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          192.168.39.30:35358         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:53564         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:51726         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:56491         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:56479         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:55990         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:56473         ESTABLISHED 10658/python
tcp        1      0 192.168.39.30:43470         192.168.39.190:3306         CLOSE_WAIT  10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:53630         ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:51495         ESTABLISHED 10658/python
tcp        1      0 192.168.39.30:43473         192.168.39.190:3306         CLOSE_WAIT  10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:55680         ESTABLISHED 10658/python
tcp        1      0 192.168.39.30:43476         192.168.39.190:3306         CLOSE_WAIT  10658/python
tcp        1      0 192.168.39.30:43472         192.168.39.190:3306         CLOSE_WAIT  10658/python
tcp        0      0 192.168.39.30:57190         192.168.39.30:5672          ESTABLISHED 10658/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:56527         ESTABLISHED 10658/python
[root@compute-57-09 admin]# netstat -anp  | grep 10659
tcp        0      0 192.168.39.30:8774          172.16.207.68:60795         ESTABLISHED 10659/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:63898         ESTABLISHED 10659/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:51432         ESTABLISHED 10659/python
tcp        0      0 192.168.39.30:57477         192.168.39.30:5672          ESTABLISHED 10659/python
tcp        1      0 192.168.39.30:43450         192.168.39.190:3306         CLOSE_WAIT  10659/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:53701         ESTABLISHED 10659/python
tcp        1      0 192.168.39.30:43451         192.168.39.190:3306         CLOSE_WAIT  10659/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:60117         ESTABLISHED 10659/python
tcp        0      0 192.168.39.30:45147         192.168.39.30:5672          ESTABLISHED 10659/python
tcp        1      0 192.168.39.30:43448         192.168.39.190:3306         CLOSE_WAIT  10659/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:51474         ESTABLISHED 10659/python
tcp        1      0 192.168.39.30:43449         192.168.39.190:3306         CLOSE_WAIT  10659/python
tcp        0      0 192.168.39.30:57226         192.168.39.30:5672          ESTABLISHED 10659/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:60879         ESTABLISHED 10659/python
tcp        1      0 192.168.39.30:43455         192.168.39.190:3306         CLOSE_WAIT  10659/python
[root@compute-57-09 admin]# netstat -anp  | grep 10660
tcp        0      0 192.168.39.30:8774          172.16.207.68:53982         ESTABLISHED 10660/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:51424         ESTABLISHED 10660/python
tcp        0      0 192.168.39.30:50736         192.168.39.30:5672          ESTABLISHED 10660/python
tcp        0      0 192.168.39.30:57846         192.168.39.30:5672          ESTABLISHED 10660/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52178         ESTABLISHED 10660/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:62032         ESTABLISHED 10660/python
tcp        0      0 192.168.39.30:57245         192.168.39.30:5672          ESTABLISHED 10660/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52220         ESTABLISHED 10660/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52414         ESTABLISHED 10660/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:60074         ESTABLISHED 10660/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52234         ESTABLISHED 10660/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:52402         ESTABLISHED 10660/python
[root@compute-57-09 admin]# netstat -anp  | grep 10661
tcp        0      0 192.168.39.30:8774          172.16.207.68:53641         ESTABLISHED 10661/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:60888         ESTABLISHED 10661/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:60957         ESTABLISHED 10661/python
tcp        1      0 192.168.39.30:43465         192.168.39.190:3306         CLOSE_WAIT  10661/python
tcp        1      0 192.168.39.30:43461         192.168.39.190:3306         CLOSE_WAIT  10661/python
tcp        0      0 192.168.39.30:47976         192.168.39.30:5672          ESTABLISHED 10661/python
tcp        0      0 192.168.39.30:57672         192.168.39.30:5672          ESTABLISHED 10661/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:51946         ESTABLISHED 10661/python
tcp        1      0 192.168.39.30:43459         192.168.39.190:3306         CLOSE_WAIT  10661/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:56618         ESTABLISHED 10661/python
tcp        1      0 192.168.39.30:43460         192.168.39.190:3306         CLOSE_WAIT  10661/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:63924         ESTABLISHED 10661/python
tcp        0      0 192.168.39.30:57233         192.168.39.30:5672          ESTABLISHED 10661/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:60964         ESTABLISHED 10661/python
tcp        1      0 192.168.39.30:43462         192.168.39.190:3306         CLOSE_WAIT  10661/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:55826         ESTABLISHED 10661/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:60803         ESTABLISHED 10661/python
tcp        0      0 192.168.39.30:8774          172.16.207.68:60633         ESTABLISHED 10661/python
[root@compute-57-09 admin]# netstat -anp  | grep 10667
tcp        0      0 192.168.39.30:58746         192.168.39.30:5672          ESTABLISHED 10667/python
tcp        0      0 192.168.39.30:58744         192.168.39.30:5672          ESTABLISHED 10667/python
[root@compute-57-09 admin]# netstat -anp  | grep 10666
tcp        0      0 192.168.39.30:58553         192.168.39.30:5672          ESTABLISHED 10666/python
tcp        0      0 192.168.39.30:58551         192.168.39.30:5672          ESTABLISHED 10666/python
[root@compute-57-09 admin]# netstat -anp  | grep 10668
tcp        0      0 192.168.39.30:55172         192.168.39.30:5672          ESTABLISHED 10668/python
tcp        0      0 192.168.39.30:55171         192.168.39.30:5672          ESTABLISHED 10668/python
[root@compute-57-09 admin]# netstat -anp  | grep 10669
tcp        0      0 192.168.39.30:55117         192.168.39.30:5672          ESTABLISHED 10669/python
tcp        0      0 192.168.39.30:55119         192.168.39.30:5672          ESTABLISHED 10669/python

反复出现:5672,rabbit_port = 5672

3306,mysql

ec2的接口没人访问,还有metadata的接口没人访问,我在虚机中访问169.254.169.254,这样应该可以建立8775连接

[root@BC-EC-85-50 ~]# netstat -anp|grep 5188
tcp        0      0 192.168.85.50:44063         192.168.85.50:5672          ESTABLISHED 5188/python
tcp        1      0 192.168.85.50:52381         192.168.85.50:3306          CLOSE_WAIT  5188/python
tcp        0      0 192.168.85.50:44064         192.168.85.50:5672          ESTABLISHED 5188/python
tcp        0      0 192.168.85.50:8774          192.168.85.50:40955         ESTABLISHED 5188/python
tcp        0      0 192.168.85.50:8776          192.168.85.50:51881         ESTABLISHED 25175/python
tcp        0      0 ::ffff:192.168.85.50:51881  ::ffff:192.168.85.50:8776   ESTABLISHED 3821/java 

通过在虚机中不断的

curl 169.254.169.254:80/openstack/latest/meta_data.json

在metadata server所在的机器上确实能够看到访问8775的连接:

tcp        0      0 192.168.85.50:34924         192.168.85.50:8775          TIME_WAIT   -
tcp        0      0 192.168.85.50:34461         192.168.85.50:8775          TIME_WAIT   -
tcp        0      0 192.168.85.50:34980         192.168.85.50:8775          TIME_WAIT   -
tcp        0      0 192.168.85.50:34664         192.168.85.50:8775          TIME_WAIT   -
tcp        0      0 192.168.85.50:34578         192.168.85.50:8775          TIME_WAIT   -    

可以大胆推测下,这个就是neutron-metadata-agent向nova meta_data server请求数据所建立的socket连接

C.nova-api不一定要监听端口,监听端口的nova-api只有一个,那就是所有nova-api的父进程,他负责监听端口,具体的通信交给它的孩子们。

D.一个python程序是否能监听多个端口?

应该可以,创建好几个socket,并监听就行

E.子nova-api每一个有什么作用呢?

貌似是nova-api代码中有好几个os_fork(),这样就创建了好几个新的进程,那么具体是干什么的呢?还得分析下代码,而且应该还能调试,good

代码中,首先启动ec2 server:

日志:

2014-10-09 11:01:51.482 INFO nova.openstack.common.service [-] Starting 4 workers
2014-10-09 11:01:51.486 INFO nova.openstack.common.service [-] Started child 5595
2014-10-09 11:01:51.492 INFO nova.openstack.common.service [-] Started child 5597
2014-10-09 11:01:51.498 INFO nova.openstack.common.service [-] Started child 5601
2014-10-09 11:01:51.503 INFO nova.openstack.common.service [-] Started child 5602

这个debug信息显示出,ec2有4个工作进程,大胆推断,一共有13个nova-api,因此,metadata,openstack,ec2,各有4个工作进程,我想应该是这样的

<span style="color: rgb(84, 84, 84); font-family: arial, sans-serif;font-size:12px; line-height: 18.2000007629395px;">再看日志,说明,每个进程都会启动一个wsgi的服务,去进行服务</span>
2014-10-09 11:01:51.604 INFO nova.ec2.wsgi.server [-] (5595) wsgi starting up on http://0.0.0.0:8773/
2014-10-09 11:01:51.614 INFO nova.ec2.wsgi.server [-] (5597) wsgi starting up on http://0.0.0.0:8773/
2014-10-09 11:01:51.625 INFO nova.ec2.wsgi.server [-] (5602) wsgi starting up on http://0.0.0.0:8773/
2014-10-09 11:01:51.623 INFO nova.ec2.wsgi.server [-] (5601) wsgi starting up on http://0.0.0.0:8773/

果然被言重:openstack的api也创建4个工作进程

2014-10-09 11:13:11.161 INFO nova.wsgi [-] osapi_compute listening on 0.0.0.0:8774
2014-10-09 11:13:11.161 INFO nova.openstack.common.service [-] Starting 4 workers
2014-10-09 11:13:11.164 INFO nova.openstack.common.service [-] Started child 6457
2014-10-09 11:13:11.168 INFO nova.openstack.common.service [-] Started child 6458
2014-10-09 11:13:11.170 INFO nova.osapi_compute.wsgi.server [-] (6457) wsgi starting up on http://0.0.0.0:8774/
2014-10-09 11:13:11.172 INFO nova.openstack.common.service [-] Started child 6459
2014-10-09 11:13:11.178 INFO nova.osapi_compute.wsgi.server [-] (6459) wsgi starting up on http://0.0.0.0:8774/
2014-10-09 11:13:11.179 INFO nova.osapi_compute.wsgi.server [-] (6458) wsgi starting up on http://0.0.0.0:8774/
2014-10-09 11:13:11.175 INFO nova.openstack.common.service [-] Started child 6460
2014-10-09 11:13:11.180 INFO nova.osapi_compute.wsgi.server [-] (6460) wsgi starting up on http://0.0.0.0:8774/

metadata api也创建4个工作进程

2014-10-09 11:13:11.220 INFO nova.wsgi [-] metadata listening on 0.0.0.0:8775
2014-10-09 11:13:11.221 INFO nova.openstack.common.service [-] Starting 4 workers
2014-10-09 11:13:11.224 INFO nova.openstack.common.service [-] Started child 6463
2014-10-09 11:13:11.227 INFO nova.openstack.common.service [-] Started child 6464
2014-10-09 11:13:11.231 INFO nova.openstack.common.service [-] Started child 6465
2014-10-09 11:13:11.238 INFO nova.metadata.wsgi.server [-] (6464) wsgi starting up on http://0.0.0.0:8775/
2014-10-09 11:13:11.239 INFO nova.metadata.wsgi.server [-] (6463) wsgi starting up on http://0.0.0.0:8775/
2014-10-09 11:13:11.235 INFO nova.openstack.common.service [-] Started child 6466

看代码:

def main():config.parse_args(sys.argv)logging.setup("nova")utils.monkey_patch()objects.register_all()gmr.TextGuruMeditation.setup_autorun(version)launcher = service.process_launcher()for api in CONF.enabled_apis:should_use_ssl = api in CONF.enabled_ssl_apisif api == 'ec2':server = service.WSGIService(api, use_ssl=should_use_ssl,max_url_len=16384)else:server = service.WSGIService(api, use_ssl=should_use_ssl)launcher.launch_service(server, workers=server.workers or 1)launcher.wait()

launcher是service.process_launcher()返回的,因此launcher.launch_service也是执行的/nova/openstack/common/service.py中的launch_serivice()

    def launch_service(self, service, workers=1):#ServiceWrapper不知道是干什么的。。。
<span style="white-space:pre">  </span>wrap = ServiceWrapper(service, workers)
<span style="white-space:pre"> </span>#wrap.workers = 4LOG.info(_LI('Starting %d workers'), wrap.workers)#循环4次,执行4次!start_child
<span style="white-space:pre">  </span>while self.running and len(wrap.children) < wrap.workers:self._start_child(wrap)

看下_start_child(wrap)的代码:

    def _start_child(self, wrap):if len(wrap.forktimes) > wrap.workers:# Limit ourselves to one process a second (over the period of# number of workers * 1 second). This will allow workers to# start up quickly but ensure we don't fork off children that# die instantly too quickly.if time.time() - wrap.forktimes[0] < wrap.workers:LOG.info(_LI('Forking too fast, sleeping'))time.sleep(1)wrap.forktimes.pop(0)wrap.forktimes.append(time.time())
<span style="white-space:pre"> </span>#创建子进程了pid = os.fork()#pid==0 子进程
<span style="line-height: 18.2000007629395px; font-family: arial, sans-serif;"><span style="white-space:pre">  </span>      if pid == 0:</span>
            launcher = self._child_process(wrap.service)while True:self._child_process_handle_signal()status, signo = self._child_wait_for_exit_or_signal(launcher)if not _is_sighup_and_daemon(signo):breaklauncher.restart()os._exit(status)LOG.info(_LI('Started child %d'), pid)wrap.children.add(pid)self.children[pid] = wrapreturn pid

上面最重要的是

launcher = self._child_process(wrap.service)
   def _child_process(self, service):self._child_process_handle_signal()# Reopen the eventlet hub to make sure we don't share an epoll# fd with parent and/or siblings, which would be badeventlet.hubs.use_hub()# Close write to ensure only parent has it openos.close(self.writepipe)# Create greenthread to watch for parent to close pipeeventlet.spawn_n(self._pipe_watcher)# Reseed random number generatorrandom.seed()
<span style="white-space:pre"> </span>#下面的应该比较重要launcher = Launcher()launcher.launch_service(service)return launcher

跟进launcher.launch_service(service)

    def launch_service(self, service):"""Load and start the given service.:param service: The service you would like to start.:returns: None"""service.backdoor_port = self.backdoor_portself.services.add(service)

跟进self.services.add(service)

    def add(self, service):self.services.append(service)self.tg.add_thread(self.run_service, service, self.done)

跟进self.tg.add_thread(self.run_service, service, self.done)

   def add_thread(self, callback, *args, **kwargs):gt = self.pool.spawn(callback, *args, **kwargs)th = Thread(gt, self)self.threads.append(th)return th

这里的callback就是run_service,但是我对于Thread(),对于pool.spawn都不熟,但是,原理上应该是创建一个线程执行run_service,service作为run_server的参数也一同传进去了,metadata,openstack,ec2对应的service应该是不同的。

    @staticmethoddef run_service(service, done):"""Service start wrapper.:param service: service to run:param done: event to wait on until a shutdown is triggered:returns: None"""service.start()systemd.notify_once()done.wait()

最终,果然进入了这个函数,调用的是service.start() nova/service.py

跟进service.start()

    def start(self):"""Start serving this service using loaded configuration.Also, retrieve updated port number in case '0' was passed in, whichindicates a random port should be used.:returns: None"""if self.manager:self.manager.init_host()self.manager.pre_start_hook()if self.backdoor_port is not None:self.manager.backdoor_port = self.backdoor_portself.server.start()if self.manager:self.manager.post_start_hook()

跟进 self.server.start()     nova/wsgi.py

    def start(self):"""Start serving a WSGI application.:returns: None"""# The server socket object will be closed after server exits,# but the underlying file descriptor will remain open, and will# give bad file descriptor error. So duplicating the socket object,# to keep file descriptor usable.dup_socket = self._socket.dup()if self._use_ssl:try:ca_file = CONF.ssl_ca_filecert_file = CONF.ssl_cert_filekey_file = CONF.ssl_key_fileif cert_file and not os.path.exists(cert_file):raise RuntimeError(_("Unable to find cert_file : %s") % cert_file)if ca_file and not os.path.exists(ca_file):raise RuntimeError(_("Unable to find ca_file : %s") % ca_file)if key_file and not os.path.exists(key_file):raise RuntimeError(_("Unable to find key_file : %s") % key_file)if self._use_ssl and (not cert_file or not key_file):raise RuntimeError(_("When running server in SSL mode, you must ""specify both a cert_file and key_file ""option value in your configuration file"))ssl_kwargs = {'server_side': True,'certfile': cert_file,'keyfile': key_file,'cert_reqs': ssl.CERT_NONE,}if CONF.ssl_ca_file:ssl_kwargs['ca_certs'] = ca_filessl_kwargs['cert_reqs'] = ssl.CERT_REQUIREDdup_socket = eventlet.wrap_ssl(dup_socket,**ssl_kwargs)dup_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR, 1)# sockets can hang around forever without keepalivedup_socket.setsockopt(socket.SOL_SOCKET,socket.SO_KEEPALIVE, 1)# This option isn't available in the OS X version of eventletif hasattr(socket, 'TCP_KEEPIDLE'):dup_socket.setsockopt(socket.IPPROTO_TCP,socket.TCP_KEEPIDLE,CONF.tcp_keepidle)except Exception:with excutils.save_and_reraise_exception():LOG.error(_("Failed to start %(name)s on %(host)s"":%(port)s with SSL support") % self.__dict__)wsgi_kwargs = {'func': eventlet.wsgi.server,'sock': dup_socket,'site': self.app,'protocol': self._protocol,'custom_pool': self._pool,'log': self._wsgi_logger,'log_format': CONF.wsgi_log_format,'debug': False}if self._max_url_len:wsgi_kwargs['url_length_limit'] = self._max_url_lenself._server = eventlet.spawn(**wsgi_kwargs)

最重要的是:self._server = eventlet.spawn(**wsgi_kwargs),但是wsgi_kwargs的参数非常重要;给出ec2的参数:

 wsgi_kwargs = {'func': eventlet.wsgi.server,   <code object server at 0x255c378, file "/usr/lib/python2.6/site-packages/eventlet/wsgi.py", line 689>'sock': dup_socket,             <eventlet.greenio.GreenSocket object at 0x3950e50>'site': self.app,               URLMap: {(None, '/services/Cloud'): <nova.api.ec2.FaultWrapper object at 0x39506d0>}'protocol': self._protocol,     eventlet.wsgi.HttpProtocol'custom_pool': self._pool,      <eventlet.greenpool.GreenPool object at 0x2d55990>'log': self._wsgi_logger,       <nova.openstack.common.log.WritableLogger object at 0x2d55e10>'log_format': CONF.wsgi_log_format,     '%(client_ip)s "%(request_line)s" status: %(status_code)s len: %(body_length)s time: %(wall_seconds).7f''debug': False}

看到这里的时候,必须要对eventlet进行一个彻底的分析,否则下面的代码是无法理解的,我们得从最基本的学起:

eventlet (http://www.choudan.net/2013/08/18/OpenStack-eventlet%E5%88%86%E6%9E%90(%E4%B8%80).html)

1. eventlet 由greenlet和select,poll,epoll组成,先来看看greenlet
2. greenlet我理解就是只能同一时间只有一个被执行的线程,具体它是什么不重要,而它能干什么才重要,例子:
import greenletdef test1(n):print "test1:",ngr2.switch(32)print "test1: over"def test2(n):print "test2:",ngr1.switch(23)print "test2: over"greenlet = greenlet.greenlet
current = greenlet.getcurrent()
gr1 = greenlet(test1,current)
gr2 = greenlet(test2,current)
gr1.switch(2)

当你创建一个greenlet,它得到一个初始化过的空堆栈;当你第一次切换到它,他会启动指定的函数,然后切换跳出greenlet。当最终栈底 函数结束时,greenlet的堆栈又编程空的了,而greenlet也就死掉了。greenlet也会因为一个未捕捉的异常死掉。(http://gashero.yeax.com/?p=112)

这句话是精华,说明什么?执行

gr1 = greenlet(test1,current)

gr1得到了一个空堆栈,当执行到

gr1.switch(2)

他所指定的函数将被启动,大胆的猜测,执行到这句话时,执行将跳转到

def test1(n):

输出test1:2

执行

<pre name="code" class="python" style="color: rgb(84, 84, 84); line-height: 18.2000007629395px;">    gr2.switch(32)

会跳转到

def test2(n):

输出: test2:32

执行

    gr1.switch(23)

这句话是最重要的,它又调回test1刚才被打断的地方,也就是将执行

 print "test1: over"

执行完了到哪去呢?不会再跳到test2了,只会退出!直接返回

gr1.switch(2)

然后退出,这个过程也很重要要理解

同理:再看一个修改的例子:

import greenletdef test1(n):print "test1:",ngr2.switch(32)print "test1: over"def test2(n):print "test2:",n#gr1.switch(23)print "test2: over"greenlet = greenlet.greenlet
current = greenlet.getcurrent()
gr1 = greenlet(test1,current)
gr2 = greenlet(test2,current)
gr1.switch(2)

输出是:

test1: 2
test2: 32
test2: over

3.所谓的父greenlet

父greenlet是当greenlet死掉时,继续原来的位置执行

每一个创建的greenlet,都有一个自己的父greenlet(显示/隐式都行)它的作用就是当子greenlet执行完成后,能回到原来的调用点继续执行
上面的例子中,似乎gr1,gr2的父greenlet是同一个?这个是这样的么??
4.greenlet的三个重要函数:

greenlet(run=None,parent=None)

创建一个greenlet对象,而不执行。run是执行回调,而parent是父greenlet,缺省是当前greenlet。

greenlet.getcurrent()

返回当前greenlet,也就是谁在调用这个函数。

greenlet.GreenletExit

这个特定的异常不会波及到父greenlet,它用于干掉一个greenlet。

5.几个greenlet之间的切换:

import greenletdef test1(x,y):z=gr2.switch(x+y)print zdef test2(u):print ugr1.switch(42)greenlet = greenlet.greenlet
#current = greenlet.getcurrent()
gr1=greenlet(test1)
gr2=greenlet(test2)
gr1.switch("hello"," world")

注意一点,gr1.switch(42)将切换回test1的

z=gr2.switch(x+y)

z将被赋值为42,其他的复杂的内容我也说不清楚,例子就是这样,输出:

hello world
42

green thread

那么在eventlet中对greenlet进行了简单的封装,就成了GreenThread,并且上面的程序还会引来一个问题,如果我们想要写一个协程,那到底该如何来控制函数的执行过程了,如果协程多了,控制岂不是很复杂了。带着这个问题来看eventlet的实现。(http://www.choudan.net/2013/08/18/OpenStack-eventlet%E5%88%86%E6%9E%90(%E4%B8%80).html)
1.我想说,下面的我也没看过,到目前为止,我认为greenlet还是比较好理解的,反正就那样呗,不过控制需要自己写,有一个疑问,同一时间只有一个协程能够被执行,为什么还要用协程呢?我在一个函数中,安排好执行的顺序不就完了么?为啥这么麻烦?

2.再精简一点:A函数要利用B函数做一些操作,很简单,调用B不就行了么?

A call B,B执行完了,一定是返回A
但是,对于greenlet,A switch to B,此时,和A就没一毛钱关系了,B执行完了,也就完了,A下面的代码将无法执行。实在想不到greenlet的应用场景,还得看别人的例子:
我试图说清楚:
def process_commands(*args):while True:line=''while not line.endswith('n'):line+=read_next_char()if line=='quitn':print "are you sure?"if read_next_char()!="y":continue    #忽略指令process_commands(line)

这是个命令行分析处理的代码,read_next_char()可以获得用户的下一个输入,cli中应该很简单

但是对于GUI程序,怎么处理呢?可以这样,当用户每次输入一个字母时,会触发一个按键的事件,在按键事件处理函数中,能获得这个字母。但请记住,GUI是消息驱动的,也就是说,不是函数
解决方法1
def process_commands(*args):

主动调用

line+=read_next_char()

获得字母,而是按键被触发之后,进入相应的处理函数,将这个字母主动告诉process_commands,如果不用greenlet,我们先思考下,我们将怎样做?

def key_event()
得到字母
将字母写到缓存中,有个标志位i表示写到第几个了
如果写的太快了,也要阻塞
def read_next_char()
也有个标志位j,从第j个缓存中读取字母,j++(要判断是否能够读即j<i)
不能读,则阻塞
因此,需要两个线程,他俩有非常明确的同步关系,但是因为线程执行的时候没有办法约束,只能使用全局变量,或者是其他的锁的技术来保证他俩的工作顺序(实际上我的解决办法是个异步的办法)
解决方法2
不要异步处理,用同步,即只要有按键,触发一个消息,阻塞在read_next_char()的代码立刻执行,将这个字母获得到,然后依然阻塞,等待用户输入
解决方法3:
看看greenlet的解决办法,greenlet有个最厉害的地方,(普通函数是调用者调用被调用者,被调用者处于一种被动的状态,只能等着被调用)而greenlet模糊了这种调用关系,试想:

<pre name="code" class="python" style="color: rgb(51, 51, 51); text-align: justify;">def process_commands(*args):

需要字母的输入时,它就切换到key_event(), 它自己被挂起了,如果没有用户输入,key_event()将挂起,有了之后,立刻切换到process_commands(),并且通过gr1.switch(参数)参数可以讲字母传回去,得到字母后,期待下一个字母,将再次切换到key_event(),可以说,完美的解决了这个问题。

贴出代码(http://www.choudan.net/2013/08/18/OpenStack-eventlet%E5%88%86%E6%9E%90(%E4%B8%80).html)
def event_keydown(key):g_processor.switch(key)def read_next_char():g_self=greenlet.getcurrent()next_char=g_self.parent.switch()    #跳到上一层(main)的greenlet,等待下一次按键return next_charg_processor=greenlet(process_commands)
g_processor.switch(*args)
gui.mainloop()

这段代码简短而精妙啊!

g_self.parent.switch()切换到哪了?这是最大的难点,
g_self=greenlet.getcurrent()

这个是在已经被切换的基础上执行的,因此已经是第二级了,通过调用g_self.parent,switch()能回到最上层的

g_processor.switch(*args)

之后继续执行,如果还看不懂,自己试验一下

如果这么说,这个greenlet确实有点用处,我明白了些,不知道你呢?
接下来看看green thread到底是被封装成什么样子了
(明天再看吧)
我又有个问题,照spawn的说法来讲,就是创建一个green thread,去执行func函数
This launches a greenthread to call func. Spawning off multiple greenthreads gets work done in parallel. The return value from spawn is a greenthread.GreenThread object, which can be used to retrieve the return value of func. See spawn for more details. 
"Spawning off multiple greenthreads gets work done in parallel"这句话有点小疑惑,不就是创建一个greenthread去执行func么?如果我在程序中,两次调用spawn,会出现什么样的情况?
(今天先到这里)

2)CONF.enabled_apis有哪些?

2014.10.09相关推荐

  1. 【跃迁之路】【605天】程序员高效学习方法论探索系列(实验阶段362-2018.10.09)...

    @(跃迁之路)专栏 实验说明 从2017.10.6起,开启这个系列,目标只有一个:探索新的学习方法,实现跃迁式成长 实验期2年(2017.10.06 - 2019.10.06) 我将以自己为实验对象. ...

  2. [转]如何解决:Android中 Error generating final archive: Debug Certificate expired on 10/09/18 16:30 的错误...

    本文转自:http://www.cnblogs.com/yyangblog/archive/2011/01/07/1929657.html 问题概述: 在导入一个app后提示如下错误: "E ...

  3. 如何解决:Android中 Error generating final archive: Debug Certificate expired on 10/09/18 16:30 的错误...

    问题概述: 在导入一个app后提示如下错误: "Error generating final archive: Debug Certificate expired on 10/09/18 1 ...

  4. Contest - 2014 SWJTU ACM 手速测试赛(2014.10.31)

    题目列表: 2146 Problem A [手速]阔绰的Dim 2147 Problem B [手速]颓废的Dim 2148 Problem C [手速]我的滑板鞋 2149 Problem D [手 ...

  5. 信息学奥赛一本通 1184 | 1934:【06NOIP普及组】明明的随机数 | OpenJudge NOI 1.10 09 | 洛谷 P1059 [NOIP2006 普及组] 明明的随机数

    [题目链接] ybt 1184:明明的随机数 ybt 1934:[06NOIP普及组]明明的随机数 OpenJudge NOI 1.10 09:明明的随机数 洛谷 P1059 [NOIP2006 普及 ...

  6. 面试题 10.09. 排序矩阵查找

    面试题 10.09. 排序矩阵查找 给定M×N矩阵,每一行.每一列都按升序排列,请编写代码找出某元素.示例:现有矩阵 matrix 如下:[[1, 4, 7, 11, 15],[2, 5, 8, 12 ...

  7. Google 宣布 GSoC 2014 计划Fwd: Google Summer of Code 2014 + 10 Things

    Hi all, GSoC 2013 刚刚结束,Google 马上宣布了 GSoC 2014 计划,也就是第十届 GSoC了~ 作为具有里程碑意义的一届,Google 推出了一系列庆祝活动,也把给学生的 ...

  8. RK3399 系列 U-BOOT (U-Boot 2014.10)

    Rockchip U-Boot 基于U-Boot 2014.10官方版本开发 Board:Nanopi M4 2G 编译配置 [Toolchain] sudo tar -jxvf arm-6.4.ta ...

  9. 纬创科技面试 2021.10.09 19:00

    纬创科技面试 面试时间:2021.10.09 19:00 面试方式:两个面试官 腾讯视频面试 面试总结:总体面试比较简单,但是问题较多,也很全面.总体上还是比较满意的 问题 基本情况: 介绍之前的项目 ...

最新文章

  1. windows无法配置此无线连接_Kubernetes 1.18功能详解:OIDC发现、Windows节点支持,还有哪些新特性值得期待?...
  2. 北大博士“最高荣誉”,出炉!
  3. linux php源码包 安装openssl 和curl 扩展
  4. Class Activation Mapping (CNN可视化) Python示例
  5. oracle索引对模糊查询,Oracle索引
  6. 我在美团Android研发岗工作的那5年,含泪整理面经
  7. scratch少儿编程第一季——07、人要衣装佛靠金装——外观模块
  8. 如何更快获取想要的设计资源?
  9. C++设计模式详解之工厂模式解析
  10. ssis 派生列_SSIS脚本组件与派生列
  11. 我已经不用 try catch 处理异常了!太辣鸡了!
  12. opencv3中camshift详解(二)camshift原理介绍
  13. 时间序列预测在R中的应用 (Part1 简介和预测工具集)
  14. python ocr 识别中文pdf_基于Python实现对PDF文件的OCR识别
  15. 五类/超五类网线与六类/超六类网线的区别及应用
  16. 男子虚构身份骗同窗网敌百余万
  17. 【正点原子Linux连载】第四十一章 嵌入式Linux LED驱动开发实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
  18. 基于C++的俄罗斯方块游戏的开发与设计
  19. 银联错失的良机,“网联”来补上
  20. 计算机硬件存在的故障,计算机硬件故障及处理.ppt

热门文章

  1. 使用爬虫爬取豆瓣电影影评数据Java版
  2. 2021年全国及上海市粮食及鲜菜人均供需情况分析:上海市本地农产品呈现自给率低的特点[图]
  3. html5 网络断开,网络连接频繁断开是怎么回事
  4. BMZCTF(泰湖杯-MISC)
  5. 门德尔松 E小调小提琴协奏曲 个人赏析
  6. CSS:运用阿里巴巴矢量库快速在对应位置加上好看的图标
  7. 解决PanDownload登录提示账号登录失败,获取bdstoken失败问题
  8. L2-032 彩虹瓶(Python3)
  9. 打造金融新生态、做一只落地利民的金融独角兽——犹太链(JEC)
  10. universe是什么牌子_有谁对NanoUniverse这个品牌有了解吗?