使用.NET Core搭建分布式音频效果处理服务(七)使用Docker压榨性能极限
docker相信很多朋友都使用过,做微服务比虚拟机还好用。
需要安装的一些东西
ffmpeg:
docker pull ffmpeg
dotnet:
docker pull dotnet
默认全是latest最新即可,具体怎么配置网上搜索一下即可。
调用用rest? 还是用rpc?
微服务之间的接口调用通常包含两个部分,序列化和通信协议。常见的序列化协议包括json、xml、bytes等;通信比较流行的是http、soap、websockect,rpc通常基于tcp实现,常用框架例如dubbo,netty、thrift。
rest:严格意义上说接口很规范,操作对象即为资源,对资源的四种操作(post、get、put、delete),并且参数都放在url上。
rpc:即我们常说的远程过程调用,就是像调用本地方法一样调用远程方法,通信协议大多采用二进制方式。
一般来说,对内选择rpc,因为他是直接基于tcp/ip协议通讯,性能要好很多。对外选择rest,因为他是更规范的、更标准的、更通用的、更简单的。
但是对于追求较高性能的rpc,会消耗额外很多成本,因此有时候对内一般也采用rest。
因此,笔者为了偷懒o(∩_∩)o ,在这个项目中选择rest,而抛弃rpc那臃肿的调用方式。
发布你的应用
dotnet 已经完全可以跨平台,但是如果直接用bin下面将文件夹拷贝到指定的地方,那么你将得到无数抓狂的错误,这是因为netcore和 net framewor本身的不同而造成,前者提供的是基础平台、让使用者自行去开发和扩展相应模块、且开源,而后者是所有东西都已经为你打包到他的集合中去了,你只管调用net系统根目录中相应的库即可。
比如你需要发布到linux平台,进入你的项目主目录。执行:
dotnet publish -r linux-x64
注意:从dotnet core 2.1开始,发布的时候已经不再需要先还原源码包(dotnet restore)。
进入到publish文件夹(一般在bin下),你会发现多了一些runtime库和一些你根本就没引用的库,这样才能有效的在其他操作系统上直接运行。
运行你的应用
你可以通过主机docker命令并附加子命令来运行docker内的dotnet程序,例如这样:
docker run -dit \ -p 50532:80 \ -v /home/dotnet/service:/wwwroot \ -w /wwwroot \ --restart always \ --name dotnet_service \ 6d25f57ea9d6 \ dotnet service.web.api.dll
-p:内外端口映射
-v:内外路径映射
-w:工作目录
6d25f....:你的dotnet镜像名称。
但笔者启动的程序需要附带大量的参数,而且不喜欢这样通过docker宿主进行命令输入,启动中有没有报错不能及时反馈(docker启动镜像返回的是一组hash代码,不会返回程序的的任何启动信息,需要通过docker log查阅),这样就变成如下操作:
进入在docker中的dotnet容器(成功运行镜像后都会成为一个容器),找到与你项目相关的主程序集文件,例如笔者是service.web.api.dll,执行dotnet service.web.api.dll(当然你也可以附带一大堆的启动参数,例如笔者这样)便可以运行这个项目。
dotnet service.web.api.dll --aspnetcore_environment=development --aspnetcore_urls=http://localhost:5052 --use_contents_directory=/home/netcore.microservice/src/service.web.api
小技巧:linux上面ssh相信大家有耳熟能详,但是一旦关闭控制台,运行的后台也将随之关闭,我们可以通过安装screen建立一个虚拟子屏幕,以保证shell程序在后台能一直运行下去。
保存你的netcore容器到镜像
如果我们需要在一台服务器上面建几十个docker容器,每一个都像上面那样进行一步一步的手动输入,那不是要崩溃...
我们保存一个已经在运行的容器,修改他子程序的运行参数,例如修改映射端口号,就可以实现快速的多个相同镜像的目的。使用命令:
docker commit c16378f943fe service_media
c1637...:这是笔者这边已经在运行的容器实例。
接下来再执行“运行你的应用”中的命令,将外部映射端口改成你想要的端口号,不断的重复这个操作,即可在同一台服务器上运行多个实例。
为何要选择docker进行实例运行
有的朋友也许不明白为何要这样做重复的操作,直接用dotnet自带的宿主,复制多条相同的命令,修改端口号一样也能达到如上的需求。
是的,这样的确也可以在同一台服务器上运行多个主机宿主实例,但是,他们并没有隔离。
对,就是这个词语----隔离:
说到这个词语可以牵涉一堆专业术语,而笔者又不想太多去复制太官方的东西,喜欢用白话文介绍自己所理解的内容。
当所有的子程序都运行在主机(非docker)下,内存分配,io读取,系统底层调用等等一些处理,都会交给主机操作系统执行,这样会存在一定的风险。而docker虽然运行在主机之上,可他却有一套自己的底层进行处理,这样带来第一层隔离,其次,运行在docker容器内的程序,容器本身也是一个操作系统,不外乎是被建立镜像的时候将操作系统进行了大范围的瘦身,只保留该tag需要的lib就行,这样又做了一层隔离。
具体详细的隔离架构,朋友们可网上搜一搜,很多的。
运行多个docker dotnet core镜像
上面噼里啪啦的说了一大堆,其实就是一张图片就解释的事情:
笔者用了三台服务器做处理服务,每台上面运行相同的docker实例32个,总共3*32=96个实例(全傻瓜式的水平扩展),通过客户端模拟100个请求,得到结论如下:
反而比单机模拟6台服务器性能降低了3%-6%,但是:
1:单机一次请求是8个,而在该系统测试中,一次请求是100个。
2:单次时间变长,是因为服务器的u比本地测试的u的主频低,但是核心却是本地u的4倍。
这样一来,其实整体性能会随着服务器的数量的添加而增加,根据业务需求而定吧,就说目前某度云的视频转换最高请求也就是几千左右,如果真有那个量级,傻瓜式的增加服务器就行了。
本系列完,感谢阅读
推荐阅读
-
使用.NET Core搭建分布式音频效果处理服务(七)使用Docker压榨性能极限
-
使用.NET Core搭建分布式音频效果处理服务(五)利用消息队列提升水平扩展灵活性
-
使用.NET Core搭建分布式音频效果处理服务(目录)
-
使用.NET Core搭建分布式音频效果处理服务(六)让MIddleware自动Invoke
-
使用.NET Core搭建分布式音频效果处理服务(一)需求、问题和解决方案的几个坑
-
使用.NET Core搭建分布式音频效果处理服务(二)创建基于FFMpeg的Web程序
-
使用.NET Core搭建分布式音频效果处理服务(五)利用消息队列提升水平扩展灵活性
-
使用.NET Core搭建分布式音频效果处理服务(七)使用Docker压榨性能极限
-
使用.NET Core搭建分布式音频效果处理服务(目录)
-
使用.NET Core搭建分布式音频效果处理服务(二)创建基于FFMpeg的Web程序