2014.10.09
<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)
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(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
2.再精简一点:A函数要利用B函数做一些操作,很简单,调用B不就行了么?
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中应该很简单
解决方法1
def process_commands(*args):
主动调用
line+=read_next_char()
获得字母,而是按键被触发之后,进入相应的处理函数,将这个字母主动告诉process_commands,如果不用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(),可以说,完美的解决了这个问题。
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=greenlet.getcurrent()
这个是在已经被切换的基础上执行的,因此已经是第二级了,通过调用g_self.parent,switch()能回到最上层的
g_processor.switch(*args)
之后继续执行,如果还看不懂,自己试验一下
2)CONF.enabled_apis有哪些?
2014.10.09相关推荐
- 【跃迁之路】【605天】程序员高效学习方法论探索系列(实验阶段362-2018.10.09)...
@(跃迁之路)专栏 实验说明 从2017.10.6起,开启这个系列,目标只有一个:探索新的学习方法,实现跃迁式成长 实验期2年(2017.10.06 - 2019.10.06) 我将以自己为实验对象. ...
- [转]如何解决: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 ...
- 如何解决: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 ...
- Contest - 2014 SWJTU ACM 手速测试赛(2014.10.31)
题目列表: 2146 Problem A [手速]阔绰的Dim 2147 Problem B [手速]颓废的Dim 2148 Problem C [手速]我的滑板鞋 2149 Problem D [手 ...
- 信息学奥赛一本通 1184 | 1934:【06NOIP普及组】明明的随机数 | OpenJudge NOI 1.10 09 | 洛谷 P1059 [NOIP2006 普及组] 明明的随机数
[题目链接] ybt 1184:明明的随机数 ybt 1934:[06NOIP普及组]明明的随机数 OpenJudge NOI 1.10 09:明明的随机数 洛谷 P1059 [NOIP2006 普及 ...
- 面试题 10.09. 排序矩阵查找
面试题 10.09. 排序矩阵查找 给定M×N矩阵,每一行.每一列都按升序排列,请编写代码找出某元素.示例:现有矩阵 matrix 如下:[[1, 4, 7, 11, 15],[2, 5, 8, 12 ...
- Google 宣布 GSoC 2014 计划Fwd: Google Summer of Code 2014 + 10 Things
Hi all, GSoC 2013 刚刚结束,Google 马上宣布了 GSoC 2014 计划,也就是第十届 GSoC了~ 作为具有里程碑意义的一届,Google 推出了一系列庆祝活动,也把给学生的 ...
- 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 ...
- 纬创科技面试 2021.10.09 19:00
纬创科技面试 面试时间:2021.10.09 19:00 面试方式:两个面试官 腾讯视频面试 面试总结:总体面试比较简单,但是问题较多,也很全面.总体上还是比较满意的 问题 基本情况: 介绍之前的项目 ...
最新文章
- windows无法配置此无线连接_Kubernetes 1.18功能详解:OIDC发现、Windows节点支持,还有哪些新特性值得期待?...
- 北大博士“最高荣誉”,出炉!
- linux php源码包 安装openssl 和curl 扩展
- Class Activation Mapping (CNN可视化) Python示例
- oracle索引对模糊查询,Oracle索引
- 我在美团Android研发岗工作的那5年,含泪整理面经
- scratch少儿编程第一季——07、人要衣装佛靠金装——外观模块
- 如何更快获取想要的设计资源?
- C++设计模式详解之工厂模式解析
- ssis 派生列_SSIS脚本组件与派生列
- 我已经不用 try catch 处理异常了!太辣鸡了!
- opencv3中camshift详解(二)camshift原理介绍
- 时间序列预测在R中的应用 (Part1 简介和预测工具集)
- python ocr 识别中文pdf_基于Python实现对PDF文件的OCR识别
- 五类/超五类网线与六类/超六类网线的区别及应用
- 男子虚构身份骗同窗网敌百余万
- 【正点原子Linux连载】第四十一章 嵌入式Linux LED驱动开发实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
- 基于C++的俄罗斯方块游戏的开发与设计
- 银联错失的良机,“网联”来补上
- 计算机硬件存在的故障,计算机硬件故障及处理.ppt
热门文章
- 使用爬虫爬取豆瓣电影影评数据Java版
- 2021年全国及上海市粮食及鲜菜人均供需情况分析:上海市本地农产品呈现自给率低的特点[图]
- html5 网络断开,网络连接频繁断开是怎么回事
- BMZCTF(泰湖杯-MISC)
- 门德尔松 E小调小提琴协奏曲 个人赏析
- CSS:运用阿里巴巴矢量库快速在对应位置加上好看的图标
- 解决PanDownload登录提示账号登录失败,获取bdstoken失败问题
- L2-032 彩虹瓶(Python3)
- 打造金融新生态、做一只落地利民的金融独角兽——犹太链(JEC)
- universe是什么牌子_有谁对NanoUniverse这个品牌有了解吗?