评估本地PyPI服务
2017-08-28 10:35:21 +08 字数:3757 标签: Python PyPI Nexus为什么需要本地PyPI服务 ¶
既然已经有了pypi.python.org这个官方源,为什么还需要一个本地源、私有源、企业源?
对于一个开发团队,如果有不止一个闭源的Python项目,并且它们之间还有相互依赖关系, 那么最好的做法,就是使用一个本地的PyPI服务,用来发布私有包。 一个Python开发团队是否有技术积累,往往取决于此。
对于一家公司,尤其是中国公司,如果深度依赖于Python的官方源, 那么也可以自建一个镜像或代理,避免一些偶然的网络可达性问题。 另外,提高访问速度、降低公网带宽压力,也是很重要的优势。
否则,Python项目只能基于代码托管平台进行发布,或者为了移植方便,只能做单文件项目。 这固然也是Python支持的方式,但毕竟太业余。 PyPI的核心优势,不仅仅在于文档与发布,还在于版本与依赖。 只要是专业的Python开发者,都明白PyPI这个平台的意义。
原理 ¶
所谓本地源、私有源、企业源,其实都是一个可以通过网络访问的目录。
其中,像pypi.python.org那样,在/simple/
下按固定结构,放置了Python包。
并且,还提供了一些网络接口,供pip
这样的包管理程序访问。
一些服务与对比 ¶
服务 | 版本 | 更新 | 镜像 | 代理 | 发布 | UI | Docker |
---|---|---|---|---|---|---|---|
pypi-legacy | 2005-08-01 | 2005-08-01 | ✘ | ✘ | ✔ | ✔ | ✘ |
warehouse | master | ~ | ✘ | ✘ | ✔ | ✔ | ✔ |
bandersnatch | 2.0.0 | 2017-04-05 | ✔ | ✘ | ✘ | ✘ | ✘ |
pypiserver | 1.2.0 | 2016-06-25 | ✘ | ✔ | ✔ | ✘ | ✔ |
devpi-server | 4.3.0 | 2017-04-23 | ✘ | ✔ | ✔ | ✘ | ✘ |
Flask-Pypi-Proxy | 0.5.1 | 2014-01-08 | ✘ | ✔ | ✔ | ✘ | ✘ |
localshop | 0.9.3 | 2015-05-15 | ✘ | ✔ | ✔ | ✔ | ✔ |
pyshop | 1.3.0 | 2017-06-29 | ✘ | ✘ | ✔ | ✔ | ✔ |
上表中的概念解释:
- 版本以实际发布版本为准。
- 更新指最新版本的发布时间。
- 镜像指是否提供定时全量同步的镜像服务。
- 代理是指下载时会自动搜寻官方的源或其它镜像,不会全量同步。 上面列出的几个有代理功能的服务,细节各不相同。
- 发布指是否允许发布私有的Python包。
- UI指是否包含某种形式的UI界面,主要是浏览器中的网页界面。 只有简陋UI的服务,也被认为是没有UI,比如devpi-server。
- Docker指在源码库中,是否自动支持Docker技术,自带Dockerfile、docker-compose.yml等文件。 即使不支持Docker的服务,也可以自制;而已经支持的服务,也只是调试方便,要实用前往往也需自制。
官方服务 ¶
官方源的界面,可以访问:
- pypi-legacy: https://pypi.python.org/
- warehouse: https://pypi.org/
孤没有对pypi-legacy进行深入研究。 它的原名似乎叫Cheese Shop,最新发布版为2005-08-01。 它应该是在2005年左右就已停止开发,虽然近期一直有提交,但应该是维护性质的。
warehouse的最新tag是v14.2.1,时间是2014年2月8日,但是至今一直有大量稳定提交。 之前预计warehouse将在2017年(今年)取代pypi-legacy, 不过至今(2017年8月)仍然只能在pypi.org访问,处于pre-production状态。
Warehouse is the next generation Python Package Repository, designed to replace the legacy code base that currently powers PyPI. Warehouse is due for public release in 2017.
现在看来,pypi-legacy的界面非常简陋,是一种本世纪初的设计风格。 而warehouse的界面就好多了,处处体现了近期的设计理念。 不过,除了界面,暂时并没看到实质性的改动。
作为私有源,warehouse可能太重了。 默认master分支上的Docker跑起来共9个容器,还是调试状态的。 需要等到它正式发布了,才能尝试使用。
bandersnatch ¶
在上表中可以看出,bandersnatch是唯一一个提供全量同步的服务。 所以,现在国内知名的PyPI镜像,基本都是实用它,比如ustc、aliyun等。
全量同步的优点突出,就是下载方便。 缺点也很明显,对服务器的硬盘、带宽的占用率非常高,有效利用率却非常低。 如果不是一家做大型Python项目的公司,比如豆瓣,这样做明显不划算。
此外,同步类方案,都有频率问题。 比如,aliyun的镜像每天一次,而ustc的每4小时一次。 在同步前,新发布的包是无法访问的。
pypiserver ¶
pypiserver是最简单的代理、发布服务。
它支持发布私有包,并且有一个非常简陋的网页,可以看到已上传的私有包。 下载时,先查找、下载私有包; 如果没发现,则查找、下载指定源中的包。
pypiserver会存储私有包,但不会缓存其它源上的包。
devpi ¶
devpi是以devpi-server为核心的一组Python包。
- devpi-server是后台服务,负责处理核心的工作,包括数据库读写、与pypi.python.org的沟通。
- devpi-client是devpi-server的CLI客户端,负责对后台服务进行设置,包括用户、库(index)管理。 客户端可以安装在任何位置。
- devpi-web是devpi-server的一个简单的前端网页界面,目前只提供搜索和版本查看功能。 前端组件必须和后台服务安装在一起。
devpi-server可以创建多个用户、仓库,并且通过一个URL对外提供。 比如,基于一个PyPI的代理(type=mirror),建立一个私有库(type=stage),只需要对外提供私有库即可。
它最大的优势是,在代理、缓存方面做得非常出色。
localshop ¶
这是一个基于Django的Web应用。 利用XMLRPC接口,localshop在pypi.python.org或其它镜像进行查找、下载。 同时,也提供一个私有发布库,并且有良好的界面展示,包括README.RST文件的预览。
同类项目有pyshop,这是一个基于Pyramid的Web应用。 相比localshop,它不提供代理服务。
相关的项目还有djangopypi,这是一个Django插件。
它是从chishop项目fork而来,可以在一个Django项目中,添加一个URL,在/pypi/
下提供PyPI的私有源服务。
这类项目中,目前还是localshop做得比较完善,开箱即用。 缺点是,有代理没有缓存。 (文档中说是有缓存功能的,但是孤在测试使用中没有配置出来。)
总结 ¶
对于资源丰富,想要全量同步、建立镜像,为公司内部、甚至外部提供高速访问服务的人来说,bandersnatch是唯一的选择。 否则,还是得从其它服务上考虑。
代理这种方式,其实还有很多小细节。 比如,是真的代理,还是假的,仅仅只是URL重定向。 这两种方式的区别是,当客户端所在的机器无法访问外部源时(比如隔离外网的工作站),前者可以正常工作,而后者不行。 当然,严格地说,重定向并不能称为代理,只是对服务端来说形式类似,前面是为了制表方便才未区分。
在真的代理中,还有是否缓存的区别。 如果没有缓存,则每次都是从被代理的源直接下载,这需要服务端对该源的访问速度够快。 如果有缓存,那么只有首次下载某个包时,才会直接下载。
服务 | 重定向 | 代理 | 缓存 |
---|---|---|---|
pypiserver | ✔ | ✘ | ✘ |
devpi-server | ✘ | ✔ | ✔ |
Flask-Pypi-Proxy | ✘ | ✔ | ✔ |
localshop | ✔ | ✔ | ✘ |
pyshop | ✔ | ✘ | ✘ |
(注:Flask-Pypi-Proxy在孤试用过程中,没有调通,所以不推荐。)
如果要有良好的前端界面,并且支持代理或重定向,那么localshop是较好的选择。 但是,没有缓存是较大的问题。 而且,即使有缓存,首次下载速度慢,也是个硬伤。 所以,多个服务进行组合,可以得到一个各方面都还行的方案。
如果只部署一个服务,那么devpi-server是首选。 如果可以再部署一个,那么可以配上localshop。 前者专门负责代理其它源,后者负责管理私有包。 假如对首次访问速度有很高要求,那么可以换成bandersnatch来与localshop搭配。
如果有闲置的开发资源,可以基于localshop,结合devpi-server的优点,开发一款新的Web App。 对大型Python开发团队来说,这应该是最好的选择。
One more thing ¶
前面说了那么多,都是Python系的。 本来,Python生态的核心部分,由Python自己来支持,思路是没错。 但评估下来发现,除了warehouse,其它的都是各有特点的小项目,而warehouse又处于开发阶段。
有没有开源的、大团队开发维护的、满足复杂需求的PyPI服务?
有,Nexus Repository Manager的OSS版本。
The world’s first and only universal repository solution that’s FREE to use.
- 文档:https://help.sonatype.com/display/NXRM3/PyPI+Repositories
- 下载:https://www.sonatype.com/download-oss-sonatype
- Docker:https://hub.docker.com/r/sonatype/docker-nexus3/
它可以管理以下形式的仓库:
- Bower
- Docker
- Git LFS
- Maven
- npm
- NuGet
- PyPI
- Ruby
- Gems
- Yum
- Proxy
其中,PyPI类的服务,支持三种:
- proxy,提供代理服务。
- hosted,提供私有包的发布服务。
- group,组合以上两类的多个服务到一起,通过同一个URL对外提供。
可以说,这一个服务,就相当于前面总结的组合服务,所有特性基本上都能打钩。 此外,OSS版内还有很多额外功能,和Pro版、以及Sonatype其它服务有很多联系。 什么安全、缺陷、开源协议等等杂七杂八的东西,都可以看到接口。
当然,它并不是没有缺点。 功能繁多,导致UI复杂而丑陋。 还有一些细节也没做好,比如代理下载时,要等它先下载完才开始提供客户端的下载。 这一点,devpi-server就做得很好,它是一边缓存、一边提供下载。
对于真正有大量多种需求的公司,它可能是目前唯一免费的选择。 企业级的应用,目前果然还是Java系的比较靠谱。