FIS源码解析-整体架构

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 本文会对FIS的整体源码架构设计进行概要性的介绍。 虽然FIS整体的源码结构比较清晰,不过讲解起来也是个系统庞大的工程,笔者尽量的挑重点的讲。如果读者有感兴趣的部分笔者没有提到的,或者是存在疑惑的,可以在评论里跑出来,笔者会试着去覆盖这些点。

序言

这里假设本文读者对{{FIS}}已经比较熟悉,如还不了解,可猛击官方文档

虽然FIS整体的源码结构比较清晰,不过讲解起来也是个系统庞大的工程,笔者尽量的挑重点的讲。如果读者有感兴趣的部分笔者没有提到的,或者是存在疑惑的,可以在评论里跑出来,笔者会试着去覆盖这些点。

下笔匆忙,如有错漏请指出。

Getting started

如在开始剖析FIS的源码前,有三点内容首先强调下,这也是解构FIS内部设计的基础。

1、 FIS支持三个命令,分别是fis releasefis serverfis install。当用户输入fis xx的时候,内部调用fis-command-releasefis-command-serverfis-command-install这三个插件来完成任务。同时,FIS的命令行基于commander这个插件构建,熟悉这个插件的同学很容易看懂FIS命令行相关部分源码。

2、FIS以fis-kernel为核心。fis-kernel提供了FIS的底层能力,包含了一系列模块,如配置、缓存、文件处理、日志等。FIS的三个命令,最终调用了这些模块来完成构建的任务。参考 fis-kernel/lib/ 目录,下面对每个模块的大致作用做了简单备注,后面的文章再详细展开。

lib/
├── cache.js    // 缓存模块,提高编译速度
├── compile.js      // (单)文件编译模块
├── config.js  // 配置模块,fis.config 
├── file.js  // 文件处理
├── log.js // 日志
├── project.js  // 项目相关模块,比如获取、设置项目构建根路径、设置、获取临时路径等
├── release.js  // fis release 的时候调用,依赖 compile.js 完成单文件编译。同时还完成如文件打包等任务。├── uri.js  // uri相关
└── util.js  // 各种工具函数

3、FIS的编译过程,最终可以拆解为细粒度的单文件编译,理解了下面这张图,对于阅读FIS的源码有非常大的帮助。(主要是fis release这个命令)

enter image description here

一个简单的例子:fis server open

开篇的描述可能比较抽象,下面我们来个实际的例子。通过这个简单的例子,我们可以对FIS的整体设计有个大致的印象。

下文以fis server open为例,逐步剖析FIS的整体设计。其实FIS比较精华的部分集中在fis release这个命令,不过fis server这个命令相对简单,更有助于我们从纷繁的细节中跳出来,窥探FIS的整体概貌。

假设我们已经安装了FIS。好,打开控制台,输入下面命令,其实就是打开FIS的server目录

fis server open

package.json可以知道,此时调用了 fis/bin/fis,里面只有一行有效代码,调用fis.cli.run()方法,同时将进程参数传进去。

#!/usr/bin/env node

require('../fis.js').cli.run(process.argv);

接下来看下../fis.js。代码结构非常清晰。注意,笔者将一些代码给去掉,避免长串的代码影响理解。同时在关键处加了简单的注释

// 加载FIS内核
var fis = module.exports = require('fis-kernel');

//项目默认配置
fis.config.merge({
   // ...
});

//exports cli object
// fis命令行相关的对象
fis.cli = {};

// 工具的名字。在基于fis的二次解决方案中,一般会将名字覆盖
fis.cli.name = 'fis';

//colors
// 日志友好的需求
fis.cli.colors = require('colors');

//commander object
// 其实最后就挂载了 commander 这个插件
fis.cli.commander = null;

//package.json
// 把package.json的信息读进来,后面会用到
fis.cli.info = fis.util.readJSON(__dirname + '/package.json');

//output help info
// 打印帮助信息的API
fis.cli.help = function(){
    // ...
};

// 需要打印帮助信息的命令,在 fis.cli.help() 中遍历到。 如果有自定义命令,并且同样需要打印帮助信息,可以覆盖这个变量
fis.cli.help.commands = [ 'release', 'install', 'server' ];

//output version info
// 打印版本信息
fis.cli.version = function(){
    // ...
};

// 判断是否传入了某个参数(search)
function hasArgv(argv, search){
    // ...
}

//run cli tools
// 核心方法,构建的入口所在。接下来我们就重点分析下这个方法。假设我们跑的命令是 fis server open
// 实际 process.argv为 [ 'node', '/usr/local/bin/fis', 'server', 'open' ]
// 那么,argv[2] ==> 'server'
fis.cli.run = function(argv){
    // ...
};

我们来看下笔者注释过的fis.cli.run的源码。

  1. 如果是fis -h或者fis --help,打印帮助信息
  2. 如果是fis -v或者fis --version,打印版本信息
  3. 其他情况:加载相关命令对应的插件,并执行命令,比如 fis-command-server
//run cli tools
fis.cli.run = function(argv){
    
    fis.processCWD = process.cwd();    // 当前构建的路径

    if(hasArgv(argv, '--no-color')){    // 打印的命令行是否单色
        fis.cli.colors.mode = 'none';
    }

    var first = argv[2];
    if(argv.length < 3 || first === '-h' ||  first === '--help'){
        fis.cli.help();    // 打印帮助信息
    } else if(first === '-v' || first === '--version'){
        fis.cli.version();    // 打印版本信息
    } else if(first[0] === '-'){
        fis.cli.help();    // 打印版本信息
    } else {
        //register command
        // 加载命令对应的插件,这里特指 fis-command-server
        var commander = fis.cli.commander = require('commander');
        var cmd = fis.require('command', argv[2]);
        cmd.register(
            commander
                .command(cmd.name || first)
                .usage(cmd.usage)
                .description(cmd.desc)
        );
        commander.parse(argv);    // 执行命令
    }
};

通过fis.cli.run的源码,我们可以看到,fis-command-xx插件,都提供了register方法,在这个方法内完成命令的初始化。之后,通过commander.parse(argv)来执行命令。

整个流程归纳如下:

  1. 用户输入FIS命令,如fis server open
  2. 解析命令,根据指令加载对应插件,如fis-command-server
  3. 执行命令

fis-command-server源码

三个命令相关的插件中,fis-command-server的代码比较简单,这里就通过它来大致介绍下。

根据惯例,同样是抽取一个超级精简版的fis-command-server,这不影响我们对源码的理解

var server = require('./lib/server.js');  // 依赖的基础库

// 命令的配置属性,打印帮助信息的时候会用到
exports.name = 'server';
exports.usage = '<command> [options]';
exports.desc = 'launch a php-cgi server';

// 对外暴露的 register 方法,参数的参数为 fis.cli.command 
exports.register = function(commander) {
    
    // 略过若干个函数

    // 命令的可选参数,格式参考 commander 插件的文档说明
    commander
        .option('-p, --port <int>', 'server listen port', parseInt, process.env.FIS_SERVER_PORT || 8080)      
        .action(function(){
            // 当 command.parse(..)被调用时,就会进入这个回调方法。在这里根据fis server 的子命令执行具体的操作
            // ...
        });
  
    // 注册子命令 fis server open
    // 同理,可以注册 fis server start 等子命令
    commander
        .command('open')
        .description('open document root directory');
};

好了,fis server open 就大致剖析到这里。只要熟悉commander这个插件,相信不难看懂上面的代码,这里就不多做展开了,有空也写篇科普文讲下commander的使用。

写在后面

如序言所说,欢迎交流探讨。如有错漏,请指出。

相关文章
|
16天前
|
存储 人工智能 并行计算
2025年阿里云弹性裸金属服务器架构解析与资源配置方案
🚀 核心特性与技术创新:提供100%物理机性能输出,支持NVIDIA A100/V100 GPU直通,无虚拟化层损耗。网络与存储优化,400万PPS吞吐量,ESSD云盘IOPS达100万,RDMA延迟<5μs。全球部署覆盖华北、华东、华南及海外节点,支持跨地域负载均衡。典型应用场景包括AI训练、科学计算等,支持分布式训练和并行计算框架。弹性裸金属服务器+OSS存储+高速网络综合部署,满足高性能计算需求。
|
30天前
|
XML Java 开发者
Spring底层架构核心概念解析
理解 Spring 框架的核心概念对于开发和维护 Spring 应用程序至关重要。IOC 和 AOP 是其两个关键特性,通过依赖注入和面向切面编程实现了高效的模块化和松耦合设计。Spring 容器管理着 Beans 的生命周期和配置,而核心模块为各种应用场景提供了丰富的功能支持。通过全面掌握这些核心概念,开发者可以更加高效地利用 Spring 框架开发企业级应用。
81 18
|
1天前
|
机器学习/深度学习 自然语言处理 算法
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
|
19天前
|
传感器 监控 安全
智慧工地云平台的技术架构解析:微服务+Spring Cloud如何支撑海量数据?
慧工地解决方案依托AI、物联网和BIM技术,实现对施工现场的全方位、立体化管理。通过规范施工、减少安全隐患、节省人力、降低运营成本,提升工地管理的安全性、效率和精益度。该方案适用于大型建筑、基础设施、房地产开发等场景,具备微服务架构、大数据与AI分析、物联网设备联网、多端协同等创新点,推动建筑行业向数字化、智能化转型。未来将融合5G、区块链等技术,助力智慧城市建设。
|
2月前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
1月前
|
自然语言处理 数据处理 索引
mindspeed-llm源码解析(一)preprocess_data
mindspeed-llm是昇腾模型套件代码仓,原来叫"modelLink"。这篇文章带大家阅读一下数据处理脚本preprocess_data.py(基于1.0.0分支),数据处理是模型训练的第一步,经常会用到。
60 0
|
3月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
140 2
|
4月前
|
缓存 Java 程序员
Map - LinkedHashSet&Map源码解析
Map - LinkedHashSet&Map源码解析
101 1
|
2月前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
创建型模式的主要关注点是“怎样创建对象?”,它的主要特点是"将对象的创建与使用分离”。这样可以降低系统的耦合度,使用者不需要关注对象的创建细节。创建型模式分为5种:单例模式、工厂方法模式抽象工厂式、原型模式、建造者模式。
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多