前端部署与效率提升:从静态到节点再到负载均衡可能有些同学了解的比较少。小公司可能后端部署,大公司会有专门的运维同学部署。部分同学对生产环境的部署接触不多,所以这次分享和总结前端项目部署相关的实践经验:从静态站点的部署,到节点项目的部署,再到负载均衡的部署,顺便分享一下提高部署效率的脚本和方法。为工作准备一台或多台服务器或虚拟机。vue或react项目的打包文件。节点项目源代码的副本。静态站点的部署静态站点的部署是指前端html/css/js资源的部署,比如vue或者react打包后生成的html、css、js文件。我们将这些文件上传到服务器后,会通过Nginx上传资源暴露在公网。上传文件到服务器就是手动将打包后的文件复制到服务器。这个很简单,但是如果每次都手动复制,部署效率会比较低,所以建议使用一些脚本或者工具。在大公司,服务器的权限一般都比较严格,可能需要各种跳板或者动态密码,而大公司一般都有专门的运维人员或者CI/CD工具。小公司可能比较自由,让个人直接ssh连接服务器。这时候可以使用rsync或者scp命令(Linux或者Mac系统)一键上传文件到服务器,提高部署效率。这里把之前使用的部署脚本分享出来,在前端项目根目录新建文件deploy.sh:#!/bin/bashfunctiondeploy(){#测试服务器test_host="root@test_server_ip"#生产服务器prod_host="root@prod_server_ip"project_path="/srv/YourProject"如果["$1"=="prod"];然后target="$prod_host:$project_path"elsetarget="$test_host:$project_path"firsync-azcuP./dist/--excludenode_modules--excludecoverage--exclude.env--exclude.nyc_output--exclude。git"$target"echo"deployto$target"}deploy$@上述脚本的意思是将/dist目录下的所有文件上传到对应服务器的/srv/YourProject目录下。测试环境的部署是直接在根目录运行./deploy.sh,会直接将/dist目录上传到root@test_server_ip服务器;生产环境的部署就是在最后加一个参数./deploy.shprod,这样就可以多环境部署了。更进一步的做法是将运行脚本的命令直接写入package.json中,如:"scripts":{"build":"vue-cli-servicebuild--modestaging","deploy":"npmrunbuild&&./deploy.sh","deploy:prod":"npmrunbuild&&./deploy.shprod"},这样就可以通过npmrundeploy命令直接打包部署到测试环境。如果你的公司还在使用手动复制或FTP工具等低效的部署方式,不妨试试使用上面的脚本来提高效率。PS:由于rsync命令只在Linux或Mac上可用,所以只有开发环境为Linux或Mac的用户才能运行。Windows用户无法运行此命令。写好网站的conf,上传文件到服务器后,就可以配置nginx了。一般nginx的配置都会放在/etc/nginx/conf.d目录下,我们在这个目录下新建一个test.conf作为项目的配置:server{listen80;server_nameyour-domain.com;#域名位置/{root/srv/YourProject;#网站源码根目录indexindex.html;}location/api{proxy_passhttp://localhost:8080;#反向代理后端接口地址}}一般来说,静态站点只需要配置上面几个就可以了,server_name表示域名,需要先解析为服务器的公网ip;root表示代码在服务器中的位置,index表示默认处理文件为index.html;location/api为反向代理后端服务(这里假设后端服务部署在本地8080端口),即your-domain.com/api的请求会被转发到http://localhost:8080。一般这种方式可以完美解决前端跨域问题。修改nginxconf后,需要重新加载nginx服务:nginx-sreloadtest如果上一步配置的域名已经解析到服务器ip,那么在公网上访问域名就可以直接访问你的站点了网络。如果不行,可以修改本机的host文件,这样配置的域名就可以在本地访问了;或者通过http://localhost。node项目的部署node项目在开发的时候可以使用nodeapp.js之类的命令来启动服务,但是如果在服务端使用这个命令,退出服务端后node进程会停止,所以需要使用node进程来保持活着的工具。现在普遍使用PM2。安装pm2npminstall-gpm2pm2的一些常用命令:pm2startapp.js#启动app.js应用pm2startapp.js-i4#集群模式模式启动app.js的4个应用实例#4个应用会自动负载均衡pm2startapp.js--name="api"#启动应用程序并将其命名为“api”pm2startapp.js--watch#文件更改时自动重启应用程序pm2startscript.sh#启动bash脚本pm2list#列出PM2启动的所有应用程序pm2monit#显示每个应用程序的CPU和内存使用情况pm2show[app-name]#显示应用程序的所有信息pm2logs#显示所有应用程序的日志pm2logs[app-name]#显示指定应用的日志pm2flushpm2stopall#停止所有应用pm2stop0#停止id为0的指定应用pm2restartall#重启所有应用pm2reloadall#重启集群模式pm2的所有应用gracefulReloadall#优雅重新加载所有应用inclustermodepm2deleteall#关闭并删除所有应用pm2delete0#删除指定应用id0pm2scaleapi10#将名为api的应用扩展到10个实例pm2reset[app-name]#重置重启次数pm2startup#创建开机自启动命令pm2save#保存当前应用列表pm2resurrect#重新加载保存的应用列表pm2update#保存进程,杀掉PM2和恢复进程pm2generate#生成示例json配置文件pm2deployapp.jsonprodsetup#Setup"prod"remoteserverpm2deployapp.jsonprod#Update"prod"remoteserverpm2deployapp.jsonprodrevert2#恢复"prod"remoteserverby2pm2module:generate[name]#Generatesamplemodulewithname[name]pm2installpm2-logrotate#安装模块(这里是一个日志轮转系统)pm2uninstallpm2-logrotate#卸载模块pm2publish#增量版本,gitpush和npmpublish用pm2启动项目一般来说我们可以直接使用pm2startapp.js--name="my-project"来启动node项目,但是这样的手动命令会很难管理,所以我们一般会在node项目的根目录下新建一个pm2.json文件来指定启动时的参数pm2启动,如:{"name":"my-project","script":"./server/index.js","instances":2,"cwd":".","exec_mode":"cluster"}name表示pm2进程名称,script表示启动的文件入口,instances表示启动的实例数(一般推荐值不大于theserverprocessor),cmd表示application服务器启动node项目时我们可以直接pm2启动pm2.json的目录。nginx代理绑定域名node项目用pm2运行后,只运行在服务器的某个端口,比如http://server_ip:3000。如果服务需要直接通过域名访问,还需要使用nginx代理到80端口。在/etc/nginx/conf.d新建my-project.conf(文件名随意,一般你可以使用网站域名.conf):server{listen80;server_nameyour-domain.com;location/{proxy_passhttp://localhost:3000;}}这是最简单的配置,可以根据实际情况添加一些参数。完成以上步骤后,一个node项目的部署就完成了。前端负载均衡部署相信很少有同学能接触??到负载均衡的部署。当一个项目的流量大到需要使用负载均衡时,通常会有专门的运维同学去做。说白了,负载均衡就是把大量的并发请求分发到多台服务器上。负载均衡架构有很多种,项目架构是一个不断演进的过程。使用哪种负载均衡架构需要具体问题具体分析,所以本文不讲什么时候使用哪种架构(笔者不会,见笑),接下来分享如何使用Nginx搭建经典的负载均衡架构从头开始的情况。NginxServer是直接暴露在前端的机器。当用户发起请求时,首先到达Nginx服务器,然后Nginx服务器通过一定的算法将请求分发到各个二级服务器(图中的Centos2、Centos3、Centos4),此时Nginx服务器作为负载负载均衡器(LoadBalancer)。笔者手头没有那么多服务器。为了演示更完整,我现在用VirtualBox创建四台虚拟机来模拟四台服务器(当然,在实在条件有限的情况下,也可以用同一台服务器的四个端口代替)。笔者创建Centos8系统的四台虚拟机假设对外有4台独立ip的服务器(假设分别为192.168.0.1、2、3、4)。如上图架构图所示,Centos1将作为前端负载均衡服务器作为NginxServer,其余Centos2、Centos3、Centos4作为应用服务器为用户提供真正的服务。接下来,让我们一步步搭建这个系统。1、应用服务器搭建服务站点。从一栋高楼开始,首先要搭建一个可以对外使用的服务。该服务可以是网站或界面。为了简单起见,我们就直接创建一个koaHelloWorld。同时,为了后面验证负载均衡的效果,部署在每台机器上的代码会稍微改动一下,比如:HelloCentos2,HelloCentos3,HelloCentos4,方便后面验证用户请求的是哪个服务器被分发到。koa演示站点已经为大家准备好了:koa-loadbalance。这里我们以虚拟机Centos2(192.168.0.2)(ip是虚构的)为例,我们将使用pm2在这个虚拟机上部署koa站点。通过scp或rsync命令上传源码到Centos2服务器还记得上面的deploy.sh脚本吗?如果将脚本添加到项目中,则可以使用npmrundeploy将其直接部署到服务器。demo源码中有这个脚本,你可以在里面更改实际ip,然后执行命令。ssh进入Centos2服务器sshroot@192.168.0.2安装node环境curl-sLhttps://rpm.nodesource.com/setup_13.x|sudobash-sudoyuminstallnodejs这里可以看到当前node有哪些版本,选择最新的OK,现在是13了。安装pm2npmipm2-gpm2启动站点在项目根目录下执行:pm2startpm2.jsonpm2list查看项目启动状态,使用curllocalhost:3000查看返回值:同样按照上面的步骤同时服务Centos3Centos4服务器部署它。(记得把index.js中的HelloXXX改掉,方便后面验证)。不出意外的话,我们的网站运行在三台服务器的3000端口:192.168.0.2:3000==>HelloCentos2192.168.0.3:3000==>HelloCentos319??2.168.0.4:3000==>HelloCentos4有些同学可能请问,为什么Centos2、Centos3、Centos4不需要安装Nginx?在实际运行中,应用服务器不需要暴露在公网中。他们只需要通过内网直接连接到负载均衡服务器,更加安全;而我们的站点是一个Node项目,本身就可以提供Web服务,所以不需要另外安装Nginx做代理或者转发。2.搭建NginxServernginx的安装方法:NginxInstall。在Centos1上安装nginx即可。3.实现负载均衡。如果你一开始没有学习过负载均衡,你可能会觉得很难,不知道如何配置。然后你会发现超级简单,因为你只需要nginx的一个配置:upstream。对于集群的所有节点,我们将上面已经部署好的Centos2、Centos3、Centos4进行集群。nginx配置类似于以下内容:upstreamAPPNAME{serverhost1:port;serverhost2:port;}APPNAME可以自定义,一般为项目名。在/etc/nginx/conf.d中新建一个upstream.conf:upstreamkoa-loadbalance{server192.168.0.2:3000;服务器192.168.0.3:3000;server192.168.0.4:3000;}这样,我们就把三台服务器整合成了一个http://koa-loadbalance的集群,下一步会用到。配置外部站点下一步是配置面向用户的网站。我们假设该网站将使用域名www.a.com,并创建a.com.conf:server{listen80;在/etc/nginx/conf.dserver_namewww.a.com下;字符集utf-8;location/{proxy_passhttp://koa-loadbalance;#这里是上面的集群名称}}配置完成后记得重启nginx-sreload完成负载均衡配置。4.测试如果你的域名是真实的,并且已经解析到nginx服务器,此时就可以直接通过域名访问了。由于笔者这里使用的是虚拟机,无法访问公网,所以配置宿主机的host,让www.a.com指向centos1服务器,然后在浏览器中打开www.a.com即可测试我们的负载均衡网站。Mac系统是sudovi/etc/hosts,在最后加一行:#IP是Centos1的ip192.168.0.1www.a.com我们在浏览器访问www.a.com,就可以了看到不断刷新,服务器返回了不同的HelloCentosX,说明我们的请求被分发到三台服务器,负载均衡配置生效。5.负载均衡的几种策略nginx的上游可以设置多种负载均衡策略。下面介绍几种常用的策略。Roundrobin(默认):每个请求按照时间顺序一个一个分配给不同的后端服务器。如果后台服务器宕机,可以自动清除。上游测试{服务器192.168.0.2:3000;服务器192.168.0.3:3000;server192.168.0.4:3000;}指定权重weight:指定轮询概率,权重与访问率成正比,用于后端服务器性能不均的情况。上游测试{服务器192.168.0.2:3000权重=5;服务器192.168.0.3:3000权重=10;server192.168.0.4:3000weight=20;}ip_hash:每个request根据访问ip的hash结果分配,让每个Visitor定时访问一个后端服务器,可以解决session问题。上游测试{ip_hash;服务器192.168.0.2:3000;服务器192.168.0.3:3000;server192.168.0.4:3000;}fair(第三方):根据后端服务器的响应时间分配请求,响应时间短的优先。上游测试{服务器192.168.0.2:3000;服务器192.168.0.3:3000;服务器192.168.0.4:3000;fair;}url_hash(third-party):根据访问的url的hash结果分配请求,使每个url指向同一个A(对应)后端服务器,当后端服务器是缓存时更有效。上游测试{服务器192.168.0.2:3000;服务器192.168.0.3:3000;服务器192.168.0.4:3000;散列$request_uri;hash_methodcrc32;}更多策略参考:ngx_http_upstream_module,根据实际情况使用以上策略,没有特殊要求也可以使用默认的轮询方式。最后从静态站点到节点站点,再到负载均衡,相信大家看完这篇文章后,对整个前端部署系统有了更全面的了解。尤其是负载均衡,接触不多的时候总觉得很复杂。其实看了之后觉得很简单。更高级的部署可能会使用Docker或k8s集群,这将在后面讨论。为了提高部署方式的效率,本文还分享了一个使用rsync命令的步骤。借助package.json脚本,一条命令即可完成部署。当然,这种方式还有很大的优化空间。真正有用的部署方式应该是持续集成。通过Jenkins或其他工具实现自动部署,推送代码自动构建部署。如果你的公司还在使用最原始的部署方式,不妨更努力地去探索一些更酷更流畅的操作。
