对PHP项目在Docker上运行的一些探索
Docker出现后,容器技术在互联网领域得到了空前的普及,无论是大公司还是屌丝创业公司的码农基本上都会在各种技术社区或者各种演讲会议上了解到过相关技术,我们作为一家屌丝创业公司也不例外,去年对Docker做了一番了解,并在年前测试了一些方案,今天在这里总结一下遇到的各种坑以及踩坑过程中的一些思考,希望能对了解过Docker并且跃跃欲试的同学有点启发,当然更欢迎在这方面有丰富经验的同学给一些建议或者指点。
这篇文章不会提及Docker的理论知识或者基本概念相关的内容,如果想了解Docker的基本使用,Docker的 官方文档 是个不错的选择,如果想了解基本的理论,可以参考下coolshell博客上的几篇文章: Docker基础技术:Linux Namespace(上) 、 Docker基础技术:Linux Namespace(下) 、 Docker基础技术:Linux CGroup 、 Docker基础技术:AUFS 、 Docker基础技术:DeviceMapper 。
一、项目环境
我们项目用的标准的PHP技术栈:PHP-FPM + Nginx,运行在阿里云的ECS上,数据库也是阿里云的服务。
二、缘起
对于一个普通的屌丝创业公司的屌丝项目来说,理论上来说是没必要用太复杂的技术的,对新技术的克制也是码农的一个职业操守。然而我之所以在项目上做这个尝试也并非是想尝试新技术,而是源自于项目上线以来遇到的各种问题,比如前面文章里有提到过的 laravel的性能问题 ,而HHVM或者PHP7这些新技术都大大提到了性能,一下子全部切换风险太大,所以可以用容器来运行某几个服务测试一下;再比如之前有出现过一个BUG,某个接口出现问题占用内存太高导致整个系统响应超时;再比如,看了各种技术大会上别人分享的经验确实想自己试一下,哈哈。
三、牛刀小试
根据Docker的理念,每个容器都是一个独立的服务,服务之间通过接口相互协作。我们采用的方案是PHP-FPM和Nginx分别跑在不同的容器中,PHP-FPM容器暴露端口给Nginx容器。
容器之间的网络通信最初用的是Docker自带的link,link虽然很简单,但是不太好用,link是通过在容器启动时修改/etc/hosts文件来实现的,当时用的时候遇到的一个问题是被link的容器重启后,这个容器IP变了,但是link的容器里并没有更新(1.10版本对link机制做了修改,不知道是否解决了这个问题,还没具体看),还有一个问题就是当同一个服务需要开多个容器时就搞不定了,当然如果是用集群的方式来跑就更搞不定了,所以link只能在本地开发时玩玩,在生产环境没啥用。最后这部分用的方案是用consul来做服务发现,关于consul就不在这里展开介绍了,有兴趣的同学可以看下这篇文章: Service Discovery for Docker Containers using Consul and Registrator 。
然后代码是放在host上,在容器启动时挂载一下代码的目录。根据接口使用的场景将接口分到了几个不同的容器里面去跑,对资源隔离做了下压力测试,符合预期,很满意!然后选了两个容器跑HHVM测试了下,确实性能提高了很多。整个结构如下图所示:
这样可以正常使用了,然后就是日志的处理,最开始挂载了一个host上的目录用来存放日志,但是这样也不太符合Docker的理念,于是就又弄了个logstash容器,将各种容器的日志写到logstash容器里面去。
然后就是对容器的监控,我们用了oneapm提供的服务,还不错,也有其他一些开源工具的选择,但是用oneapm的服务更方便一些。
一个完整的技术栈就这样搞定了,跑了几天也没出现什么问题。作为一个有追求的码农,当然是要有更高的要求的,后来想到这样一个问题:Docker的理念是容器即是一个完整的服务,但是我们的用法是把在容器内把PHP-FPM跑起来了,代码并不在里面,而是通过目录挂载的方式来实现的,这样就需要在host上面部署好代码,没有完美的实现容器即服务的理念。好,我们追求下完美!
四、完美之路
其实把代码放进容器并不只是为了去追求理念上的完美,还有另外一个用意,那就是基于Docker的CI。基本思路是每次发布都会build一个新版本的镜像,build过程中需要把代码更新到最新版本,然后安装依赖的第三方库以及其他一些业务相关的预处理,build完成后再push到registry,然后在各个节点pull下来,重启容器。整个流程如下图所示:
怎么样?这下完美了吧!如果现实也是那么完美就好了,但是偏偏现实总是会有各种各样的坑等着你!
首先,在没有用这个机制之前,发布一次代码也就几秒钟的事情,merge下分支,然后各个节点pull下代码就可以了,但是用了Docker后,merge分支后就需要build一下镜像,build后再push到registry,然后再到各个节点把镜像pull下来,少说也是要花分钟级别的。这时候有的同学可能会说Docker镜像的原理不是layer机制么,对,确实是layer,每次build只需要更新需要更新的layer就可以,但是还是没办法做到像git那样只更新那几个文件,至少要更新整个项目的代码目录。
其次,之前只需要更新一下代码就可以了,现在却需要把容器重启一下!本来重启容器是很快的,但是在容器里PHP-FPM跑起来后却很慢,我猜测是在执行docker stop时会发一个SIGTERM的信号到容器里的进程,PHP-FPM在处理SIGTERM信号时会做一些清理工作。一个节点至少有几十个容器,每个容器都重启一下非常耗时!
这样本来很简单的一个发布,用了这个「完美」的机制后却需要好几分钟。虽然整个流程完全自动化,但是确实没必要为了完美的理念做出这样一个妥协。
此外还遇到了另外一个非常奇葩的问题:升级到1.10后,容器启动后经常会遇到端口不通的情况,这时候如果进入到容器里发起一次网络请求,比如ping以下某个IP,端口就会恢复正常。用各种工具调试了很久依然没找出来问题在哪,屌丝创业公司也没精力研究这么高深的问题,只好暂时搁置了。
挣扎了很久,最后又回到了老路子。
五、面对现实
虽然没能理念上完美的方案,但是也要让整套架构更方便的扩展,比如在流量高峰期快速上架节点。得益于云计算近几年的发展,这个问题也比较容易解决。前面提到代码是放在host的一个目录,那么基本上每个host只需要三个条件就能够上线:
- 项目代码目录
- 安装Docker
- 配置好salt-minion(用来更新配置文件)
只需要在购买一台ECS后,做完上面的操作,生成一个系统镜像,需要上线新节点时用这个系统镜像来直接配置服务器即可。节点上线后,启动各个容器,通过前面提到的用consul实现的服务发现机制,自动加入集群。
六、继续探索
后面打算用Docker Swarm来简单做下集群管理,未来对调度需求比较大时可能会尝试下Mesos或者Kubernetes。不过关于容器的生态链都发展的非常快,可能等需要的时候又有更好的方案了吧。
简单总结下整个过程的感悟吧,从架构上来说,永远都没有完美的架构,只有最适合自己的架构。从码农角度来说,在做技术选型时最重要的是权衡当前项目需求、团队对各种技术了解的程度以及该技术选型带来的复杂度。切勿看了几个大牛的技术架构分享就在自己项目上跃跃欲试,最后弄的连自己都搞不定还给别人留下一个烂摊子收拾。最后,在项目迭代过程中保持项目的简单的能力永远是衡量一个码农技术的水平的重要标准。

핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전
중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기
강력한 PHP 통합 개발 환경

드림위버 CS6
시각적 웹 개발 도구

SublimeText3 Mac 버전
신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제









Laravel은 직관적 인 플래시 방법을 사용하여 임시 세션 데이터 처리를 단순화합니다. 응용 프로그램에 간단한 메시지, 경고 또는 알림을 표시하는 데 적합합니다. 데이터는 기본적으로 후속 요청에만 지속됩니다. $ 요청-

PHP 클라이언트 URL (CURL) 확장자는 개발자를위한 강력한 도구이며 원격 서버 및 REST API와의 원활한 상호 작용을 가능하게합니다. PHP CURL은 존경받는 다중 프로모토콜 파일 전송 라이브러리 인 Libcurl을 활용하여 효율적인 execu를 용이하게합니다.

Laravel은 간결한 HTTP 응답 시뮬레이션 구문을 제공하여 HTTP 상호 작용 테스트를 단순화합니다. 이 접근법은 테스트 시뮬레이션을보다 직관적으로 만들면서 코드 중복성을 크게 줄입니다. 기본 구현은 다양한 응답 유형 단축키를 제공합니다. Illuminate \ support \ Facades \ http를 사용하십시오. http :: 가짜 ([ 'google.com'=> 'Hello World', 'github.com'=> [ 'foo'=> 'bar'], 'forge.laravel.com'=>

PHP 로깅은 웹 애플리케이션을 모니터링하고 디버깅하고 중요한 이벤트, 오류 및 런타임 동작을 캡처하는 데 필수적입니다. 시스템 성능에 대한 귀중한 통찰력을 제공하고 문제를 식별하며 더 빠른 문제 해결을 지원합니다.

고객의 가장 긴급한 문제에 실시간 인스턴트 솔루션을 제공하고 싶습니까? 라이브 채팅을 통해 고객과 실시간 대화를 나누고 문제를 즉시 해결할 수 있습니다. 그것은 당신이 당신의 관습에 더 빠른 서비스를 제공 할 수 있도록합니다.

기사는 PHP 5.3에 도입 된 PHP의 LSB (Late STATIC BING)에 대해 논의하여 정적 방법의 런타임 해상도가보다 유연한 상속을 요구할 수있게한다. LSB의 실제 응용 프로그램 및 잠재적 성능

이 기사에서는 프레임 워크에 사용자 정의 기능 추가, 아키텍처 이해, 확장 지점 식별 및 통합 및 디버깅을위한 모범 사례에 중점을 둡니다.

Alipay PHP ...
