内容简介:先介绍下 swift 的代码结构:部署完成 swift 以后,就可以运行类似swift 的服务分别有:account-auditor, account-server, container-auditor, container-replicator, container-reconciler, container-server, container-sharder, container-sync, container-updater, object-auditor, object-server, objec
先介绍下 swift 的代码结构:
- bin/: Executable scripts that are the processes run by the deployer
- doc/: Documentation
- etc/: Sample config files
- examples/: Config snippets used in the docs
-
swift/: Core code
- account/: account server
- cli/: code that backs some of the CLI tools in bin/
-
common/: code shared by different modules
- middleware/: “standard”, officially-supported middleware
- ring/: code implementing Swift’s ring
- container/: container server
- locale/: internationalization (translation) data
- obj/: object server
- proxy/: proxy server
- test/: Unit, functional, and probe tests
部署完成 swift 以后,就可以运行类似 swift-init proxy start
, swift-init account-server start
, swift-init container-server start
, swift-init object-server start
, swift-init main start
, swift-init all start
等命令来启动相应的服务。
swift 的服务分别有:account-auditor, account-server, container-auditor, container-replicator, container-reconciler, container-server, container-sharder, container-sync, container-updater, object-auditor, object-server, object-expirer, object-replicator, object-reconstructor, object-updater, proxy-server, account-replicator, account-reaper
类似 start 的命令有: status, start, force-reload, stop, no-wait, no-daemon, reload, shutdown, restart, once
同时,server 和 start 的位置可以互换,还支持正则匹配符号 *, 如: swift-init proxy start
也可以用 swift-init start proxy
来代替,还可以用 swift-init pro* start
。
下面以在 proxy node 上启动 proxy server 为例来介绍,启动其他服务也是类似。
swift-init proxy start
命令后面是可以带参数的,可以用来重写配置文件中的部分配置,相关的参数可以在 bin/swift-init 中的 main 函数看到。
当运行 swift-init proxy start
命令后,首先运行的是 bin/swift-init 中的 main 函数,如下
def main(): # options为命令行输入的参数,默认值 = {'run_dir': '/var/run/swift', 'daemon': True, # 'verbose': False, 'number': 0, 'kill_wait': 15, # 'graceful': False, 'wait': True, 'once': False} # once:if it's True,父进程等待子进程结束后再往下运行 options, args = parser.parse_args() # 分割输入的命令 # eg: swift-init proxy start # then: command = start, servers = ['proxy'] command = args[-1] # 最后一个 servers = args[:-1] # 第一个到倒数第二个 # 默认启动方式是: swift-init proxy start,如果输入的是:swift-init start proxy # 那么需要将 command 和 servers 中的内容互换 commands = dict(Manager.list_commands()).keys() if command not in commands and servers[0] in commands: servers.append(command) command = servers.pop(0) # 实例化类Manager; # Manager是直接管理各个servers的类; # 初始化各个服务; manager = Manager(servers, run_dir=options.run_dir) try: status = manager.run_command(command, **options.__dict__) except UnknownCommandError: parser.print_help() print('ERROR: unknown command, %s' % command) status = 1 return 1 if status else 0
进一步看 Manager 类的构造函数,看看是怎么实例化的。其存在于 swift/swift/common/manager.py 中
class Manager(object): def __init__(self, servers, run_dir=RUN_DIR): self.server_names = set() self._default_strict = True for server in servers: # ALIASES = {'all': ALL_SERVERS, 'main': MAIN_SERVERS, 'rest': REST_SERVERS} # ALL_SERVERS, MAIN_SERVERS,REST_SERVERS 有相应的宏定义 if server in ALIASES: self.server_names.update(ALIASES[server]) self._default_strict = False # MAIN_SERVERS = ['proxy-server', 'account-server', 'container-server', 'object-server'] elif '*' in server: # 可以用*匹配server的名称,eg: swift-init pro* start self.server_names.update([ s for s in ALL_SERVERS if re.match(server.replace('*', '.*'), s)]) self._default_strict = False else: self.server_names.add(server) self.servers = set() # 依次初始化相应的服务并添加到 manager 的 servers 属性中 for name in self.server_names: self.servers.add(Server(name, run_dir))
实例化完 manager 对象后,其 servers 属性中保存了已经实例化了的需要进行操作的服务。然后调用 manager 的 run_command() 函数来对相应的服务进行操作。
class Manager(object): def run_command(self, cmd, **kwargs): # cmd 是要调用的命令,下面的之一 # ['status', 'start', 'force-reload', 'stop','no-wait', # 'no-daemon', 'reload', 'shutdown', 'restart', 'once'] f = self.get_command(cmd) return f(**kwargs) # eg: start(**kwargs),stop(**kwargs),...
调用 run_command() 后会根据在命令行输入的命令类型(如:start,restart,stop,…)来决定调用 manager 的哪个函数来对 server 进行相应的操作。
如果命令行输入的是 swift-init proxy start
,那么则会在 run_command() 中调用 start() 函数。
class Manager(object): def start(self, **kwargs): setup_env() status = 0 # kwargs是 swift-init:main() 中 options 传过来的参数 strict = kwargs.get('strict') # if strict not set explicitly if strict is None: strict = self._default_strict # 依次调用 server.launch() 启动服务 for server in self.servers: status += 0 if server.launch(**kwargs) else 1 if not strict: status = 0 if not kwargs.get('daemon', True): for server in self.servers: try: status += server.interact(**kwargs) except KeyboardInterrupt: print(_('\nuser quit')) self.stop(**kwargs) break elif kwargs.get('wait', True): for server in self.servers: status += server.wait(**kwargs) return status
我们进一步看 Server 类的 launch() 函数是如何启动一个服务的。
class Server(object): def launch(self, **kwargs): conf_files = self.conf_files(**kwargs) if not conf_files: return {} # 获取正在运行的进程,返回一个 {pids:pid_files} 的字典 # 如果没有进程在运行则返回空 pids = self.get_running_pids(**kwargs) # pids 不为空则表示已经有进程在运行 # 下面判断服务是否启动 already_started = False for pid, pid_file in pids.items(): conf_file = self.get_conf_file_name(pid_file) # for legacy compat you can't start other servers if one server is # already running (unless -n specifies which one you want), this # restriction could potentially be lifted, and launch could start # any unstarted instances if conf_file in conf_files: already_started = True print(_("%(server)s running (%(pid)s - %(conf)s)") % {'server': self.server, 'pid': pid, 'conf': conf_file}) elif not kwargs.get('number', 0): already_started = True print(_("%(server)s running (%(pid)s - %(pid_file)s)") % {'server': self.server, 'pid': pid, 'pid_file': pid_file}) if already_started: print(_("%s already started...") % self.server) return {} # START_ONCE_SERVERS 表示在 ALL_SERVERS 中,但不在 MAIN_SERVERS # 即,除 'proxy-server', 'account-server', 'container-server', # 'object-server' 之外的所有服务 if self.server not in START_ONCE_SERVERS: kwargs['once'] = False pids = {} for conf_file in conf_files: if kwargs.get('once'): msg = _('Running %s once') % self.server else: msg = _('Starting %s') % self.server print('%s...(%s)' % (msg, conf_file)) try: # 启动服务 pid = self.spawn(conf_file, **kwargs) except OSError as e: if e.errno == errno.ENOENT: # TODO(clayg): should I check if self.cmd exists earlier? print(_("%s does not exist") % self.cmd) break else: raise pids[pid] = conf_file return pids
swift 中各个 server 的进程 pid 都是写入到文件中,默认保存在路径 /var/run/swift 下,我们看到上面 launch() 先查看指定路径下是否存在相应的文件,从而判断相应的服务是否已经启动,如果没有启动再调用 spawn() 启动。下面进一步看 spawn() 函数。
class Server(object): def spawn(self, conf_file, once=False, wait=True, daemon=True, additional_args=None, **kwargs): """Launch a subprocess for this server. :param conf_file: path to conf_file to use as first arg :param once: boolean, add once argument to command :param wait: boolean, if true capture stdout with a pipe :param daemon: boolean, if false ask server to log to console :param additional_args: list of additional arguments to pass on the command line :returns: the pid of the spawned process """ args = [self.cmd, conf_file] if once: args.append('once') if not daemon: # ask the server to log to console args.append('verbose') if additional_args: if isinstance(additional_args, str): additional_args = [additional_args] args.extend(additional_args) # figure out what we're going to do with stdio if not daemon: # do nothing, this process is open until the spawns close anyway re_out = None re_err = None else: re_err = subprocess.STDOUT if wait: # we're going to need to block on this... re_out = subprocess.PIPE else: re_out = open(os.devnull, 'w+b') # 创建并返回一个子进程,args[0],可执行文件名,args[1:]是参数 # args = ['swift-**-server', '/etc/swift/**-server.conf'] proc = subprocess.Popen(args, stdout=re_out, stderr=re_err) # 获取 pid_file 路径,eg: /var/run/swift/***-server.pid pid_file = self.get_pid_file_name(conf_file) # 将 proc.pid 写入到 pid_file write_file(pid_file, proc.pid) self.procs.append(proc) return proc.pid
至此大致流程已经分析完毕
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 源码分析SpringBoot启动
- kubelet 分析源码:启动流程
- mybatis源码分析:启动过程
- gin 源码阅读(一)-- 启动
- 【zookeeper源码】启动流程详解
- ReactNative源码解析-启动流程
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
设计模式
[美] Erich Gamma、Richard Helm、Ralph Johnson、John Vlissides / 李英军、马晓星、蔡敏、刘建中 等 / 机械工业出版社 / 2000-9 / 35.00元
这本书结合设计实作例从面向对象的设计中精选出23个设计模式,总结了面向对象设计中最有价值的经验,并且用简洁可复用的形式表达出来。书中分类描述了一组设计良好、表达清楚的软件设计模式,这些模式在实用环境下特别有用。此书适合大学计算机专业的学生、研究生及相关人员参考。 书中涉及的设计模式并不描述新的或未经证实的设计,只收录了那些在不同系统中多次使用过的成功设计。一起来看看 《设计模式》 这本书的介绍吧!
HEX HSV 转换工具
HEX HSV 互换工具
HSV CMYK 转换工具
HSV CMYK互换工具