zoukankan      html  css  js  c++  java
  • Ruby on rails 项目启动流程

    众所周知,我们可以通过rails s 这个命令来启动一个rails 项目,但是这条命令都干了哪些事呢?抽时间研究了下,同时感谢tomwang1013的博客。当我们输入rails s 这个命令的时候,项目会加载项目bin/rails.rb 这个文件 
    #!/usr/bin/env ruby 
    APP_PATH = File.expand_path('../../config/application', __FILE__) 
    require_relative '../config/boot' 
    require 'rails/commands'
     
    通过代码我们可以看到这个文件中定义了一个APP_PATH 即我们的项目文件:config/application.rb,并require了config/boot,boot文件主要是做了bundle的初始化。 
    然后,我们可以看到这个时候rails/commands(railties-3.2.3/lib/rails/commands.rb)文件被load进来,由于我们传入的command参数为s,也就是server,然后我们看看commands的这个文件的源码对应的部分:

    when 'server'                                                                                         
      # Change to the application's path if there is no config.ru file in current dir.                    
      # This allows us to run script/rails server from other directories, but still get                   
      # the main config.ru and properly set the tmp directory.                                            
      Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru"))  
    
      require 'rails/commands/server'                                                                     
      Rails::Server.new.tap { |server|                                                                    
        # We need to require application after the server sets environment,                               
        # otherwise the --environment option given to the server won't propagate.                         
        require APP_PATH                                                                                  
        Dir.chdir(Rails.application.root)                                                                 
        server.start                                                                                      
      }    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在server 这个方法中我们通过server.start这行代码可以看出最终调用了start这个方法,然后查看下start 这个方法。同时这里面也打印了我们熟悉的控制台信息

    def start                                                                          
      url = "#{options[:SSLEnable] ? 'https' : 'http'}://#{options[:Host]}:#{options[:Port]}"  
      puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"                 
      puts "=> Rails #{Rails.version} application starting in #{Rails.env} on #{url}"  
      puts "=> Call with -d to detach" unless options[:daemonize]  
      trap(:INT) { exit }  
      puts "=> Ctrl-C to shutdown server" unless options[:daemonize]  
      #Create required tmp directories if not found                                    
      %w(cache pids sessions sockets).each do |dir_to_make|                            
        FileUtils.mkdir_p(Rails.root.join('tmp', dir_to_make))                         
      end                                                                              
    
      puts 'server start ---'  
      super  
    ensure  
      # The '-h' option calls exit before @options is set.                             
      # If we call 'options' with it unset, we get double help banners.                
      puts 'Exiting' unless @options && options[:daemonize]                            
    end   
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这个start 这个方法最终会执行super 这个,super 会调用Rack::Server#start方法:代码

    def start &blk  
      if options[:warn]  
        $-w = true                                                     
      end                                                              
    
      if includes = options[:include]  
        $LOAD_PATH.unshift(*includes)                                  
      end  
    
      if library = options[:require]                                   
        require library  
      end  
    
      if options[:debug]  
        $DEBUG = true                                                  
        require 'pp'  
        p options[:server]                                             
        pp wrapped_app  
        pp app  
      end  
    
      # Touch the wrapped app, so that the config.ru is loaded before  
      # daemonization (i.e. before chdir, etc).                        
      wrapped_app  
    
      daemonize_app if options[:daemonize]                             
      write_pid if options[:pid]  
    
      trap(:INT) do  
        if server.respond_to?(:shutdown)                               
          server.shutdown  
        else                                                           
          exit  
        end                                                            
      end  
    
      server.run wrapped_app, options, &blk  
    end  
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    代码执行到server.run wrapped_app 这行代码。wrapped_app方法最终又会调用Rack::Server#app

    def app  
      @app ||= begin                                                                
        if !::File.exist? options[:config]                                          
          abort "configuration #{options[:config]} not found"                       
        end  
    
        app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)  
        self.options.merge! options  
        app  
      end  
    end     
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    最终app 这个方法会加载项目config 目录下的environment.rb这个文件如:

    # Load the Rails application.
    require File.expand_path('../application', __FILE__)
    require 'whenever'
    
    
    module ProductConfig
      DYNAMIC_FIELDS = Hash.new
    end
    
    module RestConfig
      PRODUCT_SERVER = ENV["PHOTO_HOST"] || 'http://localhost:3001/'
    
      #CUSTOMER_SERVER = ENV["CUSTOMER_HOST"] || 'http://localhost:3001/'
      CUSTOMER_SERVER = ENV["CUSTOMER_HOST"] || 'http://localhost:3001/'
    
      OA_SERVER = 'http://localhost:3001/'
    
      #ELEPHANT_HOST = ENV["ELEPHANT_HOST"] || 'http://www.jiuyunda.net:90/'
      ELEPHANT_HOST = ENV["ELEPHANT_HOST"] || 'http://localhost:3001/'
    
      JXC_HOST = ENV["JXC_HOST"] || 'http://localhost:3001/'
    
      SETTLE_HOST = ENV["SETTLE_HOST"] || 'http://localhost:3001/'
    
    end
    
    # Initialize the Rails application.
    Rails.application.initialize!
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    Rails.application.initialize!这行代码我们可以看出 
    项目的初始化完成。这个时候我们代码就回到Rack::Server#start方法的最后一行 server.run wrapped_app, options, &blk 由于我们没有设定任何参数。通过代码

    def server                                                                         
      @_server ||= Rack::Handler.get(options[:server]) || Rack::Handler.default(options)  
    end      
    def self.default(options = {})          
      # Guess.                              
      if ENV.include?("PHP_FCGI_CHILDREN")  
        # We already speak FastCGI          
        options.delete :File                
        options.delete :Port                
    
        Rack::Handler::FastCGI              
      elsif ENV.include?("REQUEST_METHOD")  
        Rack::Handler::CGI                  
      else                                  
        begin                               
          Rack::Handler::Thin               
        rescue LoadError                    
          Rack::Handler::WEBrick            
        end                                 
      end                                   
    end            
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    我们可以看到rack 为我们选定了默认的server.一般来说是WEBrick .然后WEBrick启动,打印如下信息

    INFO  WEBrick 1.3.1  
    INFO  ruby 1.9.3 
    INFO  WEBrick::HTTPServer#start: pid=28371 port=3000 
    • 1
    • 2
    • 3

    如果安装了其他application server的话打印的信息可能会不同如

    Booting Puma
    => Rails 4.2.4 application starting in development on http://localhost:3000
    => Run `rails server -h` for more startup options
    => Ctrl-C to shutdown server
    "assets end:false"
    Puma starting in single mode...
    * Version 3.4.0 (ruby 2.3.0-p0), codename: Owl Bowl Brawl
    * Min threads: 0, max threads: 16
    * Environment: development
    * Listening on tcp://localhost:3000
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    至此项目的启动已完成。

  • 相关阅读:
    19、spring注解学习(声明式事务)——spring注解版声明式事务
    Visual C# 2015调用SnmpSharpNet库实现简单的SNMP元素查询
    SNMP协议交互学习-获取udp的udpindatagrams
    LwIP的SNMP学习笔记
    stm32f407使用Keil uV5建立工程日志
    IP unnumbered interface,某个接口不编号,某个接口不分配IP地址
    OSPFv3与OSPFv2协议的比较
    卫星网络-拓扑优化-文献笔记
    卫星轨道相关笔记SGP4
    [20190226]删除tab$记录的恢复6.txt
  • 原文地址:https://www.cnblogs.com/lmg-jie/p/8998959.html
Copyright © 2011-2022 走看看