阅读更多

0顶
0踩

开源软件
近日搜狐公司开源了其Python项目自动化部署工具 essay,功能在Github主页上的readme上进行了详细介绍。那该项目诞生时的外围情况、产生环境、一些决策的考虑都是怎么样的呢?下面我们听听来自该项目组成员the5fire的讲述(下文转载自the5fire的技术博客)。

诞生之初

事情还得从头开始说起,从那些自动化的fabric文件开始,也从我刚入职搜狐负责手机搜狐开发开始说起。我参与开发的时候项目的部署已经是自动化了,不过并没有抽象出一个工具来。那会儿主要由两个项目,一个基于tornado,一个基于Django。两个项目都有各自的发版方法,但逻辑基本一致。

两个项目的上线流程都是先打包(py的源码包),然后在通过内部的pypiserver安装到各个服务器上,由supervisord启动、管理。

随着业务的发展,新的项目逐渐多了起来。这时一个新的项目开发流程是这样的:先从就项目中把fabfile(fabric的配置文件)和supervisord配置文件以及setup.py文件拷贝过来,然后再往里面填源码。流程依然是一致的。

这就是一开始的状态,混沌中带着那么一点秩序。

开始造轮子

说起来,程序员都是十足的懒人。这样copy的方式多少让自己都有点不忍直视,于是 @熊总 建议我们不如造这样一个轮子,让所有的项目都能在这上面滚起来。于是把这个造轮子的任务交给我来做,刚好我也是懒人一个,于是很happy的开始了。

要造一个通用的轮子,必然是要把项目中用到的部分抽象出来,哪些部分是通用的呢,这只有深切参与到项目的开发和部署中才能体会得到。刚好在那段时间之前,我也参与了修改bug,打包,部署上线的过程,包括copy那些打包的脚本和配置文件。

有了上面的经验,只要把必需的东西输出就行了。总结了一下,当时项目的打包和上线涉及到这几个方面:

  1. 打包 —— 生成版本号,渲染setup中的版本和项目信息,然后放到pypi server的packages目录下
  2. 虚拟环境 —— 在新的服务器上创建虚拟环境
  3. 安装项目 —— 从pypiserver安装项目到虚拟环境中
  4. 启动supervisord —— 管理项目进程
  5. 切换nginx配置 —— 我们有两套环境在线上同时运行,可以称为a环境和b环境,主要用于上线以及线上突然出现问题时回滚
细分的话就上面五个步骤,不太理解的可以去看看我们的essay说明。也就是只要满足了这些功能,那么这轮子就算是完成了。另外还考虑到为了便于新项目的开发,还需要能自动创建具备这些功能的项目模板。这其实是最主要的痛点,总是拷贝什么的最没技术含量了。

于是添加了创建项目并且初始化模板,然后还能初始化到gitlab或者github上。

这样的工具俨然是项目开发部署、居家旅行之良品。

争论之处

需求明确之后,怎么组织项目的代码呢,对于正常的web项目来说,没有啥难度的,都有固定的模板。对于这个工具类的东西,还是第一次考虑,怎么设计才能更合理——易扩展、易维护。在翻了好久django的源代码之后,我开始按照一个core,然后一些tools的思路开始码代码。

我的考虑是,这个工具应该有一个核心的功能,然后是周围的一些辅助工具。遗憾的是,这种思路最后还是被推翻了。熊总的意思是应该参考linux的pipeline来设计,所有的功能都应能单独拿出来。于是底层的工具模块都按照这个逻辑被他重写了(so,如果你们觉得那部分代码有槽点尽管吐好了,我不介意的,^_^)。

代码结构的争论还好些,基于经验就能看出哪种更好。但是一些逻辑的设计却不是经验能得到的,就像软件开发没有银弹一样,各自的业务场景都不同,没有统一的解决方案。

另外一个争执的点是部署方式。如果你已经看了我们的文档,或者已经理解了上面的部署方式。你可能已经疑惑了:“为毛你们不直接用git部署呢?还可以打tag什么的。” 这也是我们之前在考虑的问题。

摆在我们面前的有两条路,一条路是用git来部署代码,另外一条路是用pip install项目包来部署。我们选择了后者。原因是这样的::

  1. 历史原因 —— 之前的项目一直在用这样的方式
  2. 服务器配置的成本 —— 这个我觉得是最主要的,对比两种方式,git部署的话服务器要统一安装git环境,但是我们申请到新的服务器没有这东西,我们得自己安装;另外还有一个包依赖的问题。而使用pip的方式安装,不需要做多余的处理,新来机器,给了ip,直接就能部署上去。
大概就基于上述的两个原因,选择了用pip install的方式来部署了。有什么没说到得地方,有同事路过留言补充下吧。

开放的初衷

有了上面的过程,也就产生了这么个工具: essay 。在项目完成之后,后面的时间里我们划分了不同的组,又开始负责新的项目。这个工具算是一直在我们的项目开发中起着重要的作用。我们觉得这个工具算是我们在过去一年多中开发和部署经验的总结,开放出来应该会有些价值,无论是对于开发者还是对于团队。

我自己是在这个工具的开发过程中学到很多东西,我想任何一个渴望了解项目从开发到部署整个流程的开发人员都应该能从中有所收益。

开放的目的除了分享经验,还有一个重要的作用就是交流。我们所积累的经验在业内并不一定是最佳的,肯定还有更多更好的解决方案,而这些东西都要来源于交流。这样才能相互促进,而相互促进才是开放和开源的初衷。

项目地址:https://github.com/SohuTech/essay

数据补充

手机搜狐网(m.sohu.com)每天有几亿的PV,在这样的情况下,发现线上bug,一般情况下从修复bug到上线不会超过15分钟。并且在上线的时候用户是不会感觉到页面访问慢或者打不开的。在新功能点或者bug多的情况下,一天上线十几个版本的情况也是有的。每次上线都不会对用户造成影响的关键在于我们部署了a,b两套环境。

之前在我参与手机搜狐网开发时后台有100多台虚机,在遇到热点事件的时候会扩充一倍。在这种情况下,新功能上线的过程我印象中不会超过5分钟,如果关闭fabric的success的console输出以及开启并行模式,发布的速度会更快。
来自: the5fire博客
0
0
评论 共 3 条 请登录后发表评论
3 楼 dohkoos 2013-11-26 19:10
大公司开源,小猿猿贡献代码,大公司可以依靠小猿猿完善自己的产品,还不需要付钱
然后
......
大公司闭源,卖产品产品品
2 楼 tuhaihe 2013-11-26 14:35
ray_linn 写道
搜狐还有项目哪,稀奇。

很多公司都有自己的开源项目,大家慢慢认识到了项目开源的好处。
1 楼 ray_linn 2013-11-26 14:34
搜狐还有项目哪,稀奇。

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 动态链接库(stdcall def 等等)(博客相关代码)

    博客中用到的代码 http://blog.csdn.net/silyvin/article/details/8984885

  • C语言中调用函数

    在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致。如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准。对数值型数据,可以自动进行类型转换。即。

  • c++中的__stdcall、__declspec(dllexport)、__declspec(dllimport)

    如果未定义 MATHLIBRARY_EXPORTS

  • c语言函数调用及应用举例

    一,函数的定义 一般来说,执行源程序就是执行主函数main,其他函数只能被主函数所调用,而其他函数之间也可以相互调用。 1.标准库函数: 分为:I/O函数,字符串,字符处理函数,数学函数,接口函数,时间转换和操作函数,动态地址分配函数,目录函数,过程控制函数,字符屏幕和图形功能函数。 这些库函数在不同的头文件中声明。比如: math.h头文件中有:sin(x),cos(x),exp(x)...

  • 调用约定

    一:调用约定的影响: (1)影响符号的生成规则 (2)影响形参的入栈顺序 我们常用的四种都是从右向左入栈 (3)影响形参的开辟和清理方式 二:四种调用约定 1._cdecl: 开辟:调用方 清理:调用方 2._stdcall: 开辟:调用方 清理:调用方 3._fastcall: 形参字节小于等于四字节:前两个不开辟内存,寄存器带入被调用方,第三个参数开始与_stdca...

  • 调用约定(Calling convention)详解(__stdcall,__cdecl,__fastcall)

    #define   CALLBACK         __stdcall   #define   WINAPI             __stdcall   #define   WINAPIV           __cdecl   #define   APIENTRY          WINAPI   #define   APIPRIVATE       __stdcall   #defin

  • C#调用C++ dll时CallingConvention调用约定详解

    C#调用C++ dll时,我们会在引入方法上写CallingConvention属性,这是指定调用在非托管代码中实现的方法所需的调用约定。 c++   输出的函数调用约定是多种的  1、Cdecl   调用方清理堆栈。 这使您能够调用具有 varargs 的函数(如 Printf),使之可用于接受可变数目的参数的方法。 2、FastCall   不支持此调用约定。     

  • C# 调用Dll

    net平台上,调用dll文件有2种含义1、调用托管dll,即你使用。net平台开发的dll,属于托管代码2、调用非托管dll,即传统的dll,一般是C++,VB,DELPHI等等开发出来的,属于非托管代码。从你的意思中看出来你现在是调用托管的dll,方法是 “在解决方案管理器” - “解决方案”(或项目) 中的任意地方, 右键“添加引用”,“浏览”,选择你需要调用的dll文件...

  • C#调用C++DLL,及回调函数、string参数传递的总结

    Int型传入: Dll端: extern "C" __declspec(dllexport) int Add(int a, int b) {     return a+b; } C#端: [DllImport("aeClient2.0.dll", CallingConvention =CallingConvention

  • 白盒测试用例设计方法之逻辑覆盖

    文章目录逻辑覆盖语句覆盖(SC)判定覆盖(DC)条件覆盖(CC)条件判定组合覆盖(CDC)多条件覆盖/条件组合覆盖(MCC)修订判定条件覆盖(MCDC) 逻辑覆盖 通过对程序逻辑结构的遍历实现程序的覆盖。 示例(C语言): int function1 (bool a,bool b,bool c) { int x; x=0; if (a && (b || c)) x=1; return x; } 流程图如下: Created with Raphaël 2.2.0开始x=0(a) AND (

  • 函数类型和函数指针

    本文将给大家带来函数类型和函数指针的使用方法以及概念介绍。函数指针其实和普通的指针是一样的,只是指向不同而已,大家不用害怕。

  • MFC学习--CallBack问题

    使用__stdcall, 函数的调用就不在是调用者负责清空函数栈, 而是由函数自身. 更直白的说就是倒底是在被调用的函数中清理, 还是在调用的函数中清理. _cdecl则需要调用函数自身进行清理, 而这样就无法达到跨平台调用. 所以__stdcall和_cdcel区分了处理堆栈时的责任归属. 比如传统windows程序的WinMain入口的定义:int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine

  • typedef函数指针与函数类型的定义及使用方式

    typedef函数指针与函数类型的定义及使用方式 原创 2015年08月10日 21:17:31 1946 1、先给出一道面试题: #include"stdafx.h" #include"stdio.h" //实现数值的自增1 int inc(int a) {           return(++a);

  • dll编写为什么加上 extern "C" 和 __stdcall /__cdecl

    C方式编译(extern "C"): __stdcall调用约定:输出名称在原名称前加一下划线,后面再加上一个“@”和其参数的总字节数(_原名称@参数总字节数),如名称int Func_C_stdcall(int a,int b)输出为_Func_C_stdcall@8;__cdecl调用约定:与原名称相同,如名称int Func_C_cdecl(int a,int b)输出还是为Fun

  • typedef 用法(定义数据 定义函数 基础)

    C语言语法简单,但内涵却博大精深;如果在学习时只是止步于表面,那么往往后期会遇到很多困 难。typedef是C语言中一个很好用的工具,大量存在于已有代码中,特别值得一提的是:C++标准库实现中更是对typedef有着大量的使用。但很 多初学者对其的理解仅局限于:typedef用来定义一个已有类型的"别名(alias)"。正是因为有了这样的理解,才有了后来初学者在typedef int myint和...

  • c语言函数的调用

    学习笔记

Global site tag (gtag.js) - Google Analytics