本文记叙我作为一个完全不懂ror(ruby on rails)的开发者,了解ror以及cc所需的知识。全文包括了cloud controller的代码结构,MVC架构分析,最后有一个例子帮助分析。
cc是一个ror项目,所以是按照ror的目录结构来安排的,如下所示。
it 'should add the environment variable if its legal' do @args['env'] = ['foo=bar'] headers_for(@user, nil, @args).each { |key, value| request.env[key] = value } post :create get :get, :name => @app_name Yajl::Parser.parse(response.body)['env'].should == ['foo=bar'] end从第一行就可以看出,这块代码是check环境变量已经加载了,do代码块最后一行就是env环境变量should等于 ['foo=bar']。
if not CloudController.use_nginx server = Thin::Server.new(CloudController.bind_address, CloudController.external_port) else socket = CloudController.instance_socket port = CloudController.instance_port if socket and port $stderr.puts "only one of instance_socket or insecure_instance_port should be enabled in config file...quiting..." exit 1 end if socket server = Thin::Server.new(socket) else $stderr.puts "Warning!!! starting up in a known insecure configuration." server = Thin::Server.new('127.0.0.1', port) end end cc_rack = File.join(cc_root, 'config.ru') server.app = Rack::Adapter.load(cc_rack) # The routers proxying to us handle killing inactive connections. Set an upper limit # just to be safe. server.timeout = 15 * 60 # 15 min server.start我们可以看到cc使用了Thin的web服务器,而同时load了一个rack。这个rack就是通过读取config.ru来生成的。
get 'apps' => 'apps#list', :as => :list_apps get 'apps/:name' => 'apps#get', :as => :app_get put 'apps/:name' => 'apps#update', :as => :app_update delete 'apps/:name' => 'apps#delete', :as => :app_delete put 'apps/:name/application' => 'apps#upload', :as => :app_upload get 'apps/:name/crashes' => 'apps#crashes', :as => :app_crashes post 'resources' => 'resource_pool#match', :as => :resource_match get 'apps/:name/application' => 'apps#download', :as => :app_download每一行的第一项显然是request类型,第二项是url格式,:name表示有一个参数,这个参数被命名为name,箭头后面的则是对应的controller及其方法名,比如apps#list就是调用apps的list方法。最后一个as就是规则的一个别名,暂时不清楚什么作用。。
vmc接收到用户指令会发送一个请求,在vmc/ib/cli/commands/apps.rb类的change_instances方法中调用了client的update_app方法:
client.update_app(appname, app)然后client会执行
json_put(path(VMC::APPS_PATH, name), manifest)
我还没有完全了解vmc的运行,这个instance的具体操作应该是藏在这些参数里面的,然后put完之后会发送到server端。
put 'apps/:name' => 'apps#update', :as => :app_update
if changed.include?('instances') manager.change_running_instances(delta_instances) manager.updated user_email = user ? user.email : 'N/A' CloudController.events.user_event(user_email, app.name, "Changing instances to #{app.instances}", :SUCCEEDED) endmanager就是models里面的app_manager。这个delta_instances就是需要改变的量,比如-1就是减少一个。
dea_id = find_dea_for(message) json = Yajl::Encoder.encode(message) if dea_id CloudController.logger.debug("Sending start message #{json} to DEA #{dea_id}") NATS.publish("dea.#{dea_id}.start", json)首先find一个dea,然后向NATS发布一个dea start 的消息,让dea start instance,然后就ok了