欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用.NET Core搭建分布式音频效果处理服务(七)使用Docker压榨性能极限

程序员文章站 2022-12-29 14:49:57
Docker相信很多朋友都使用过,做微服务比虚拟机还好用。 需要安装的一些东西 ffmpeg: dotnet: 默认全是latest最新即可,具体怎么配置网上搜索一下即可。 调用用REST? 还是用RPC? 微服务之间的接口调用通常包含两个部分,序列化和通信协议。常见的序列化协议包括json、xml ......

使用.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镜像

上面噼里啪啦的说了一大堆,其实就是一张图片就解释的事情:

使用.NET Core搭建分布式音频效果处理服务(七)使用Docker压榨性能极限

笔者用了三台服务器做处理服务,每台上面运行相同的docker实例32个,总共3*32=96个实例(全傻瓜式的水平扩展),通过客户端模拟100个请求,得到结论如下:

反而比单机模拟6台服务器性能降低了3%-6%,但是:

1:单机一次请求是8个,而在该系统测试中,一次请求是100个。

2:单次时间变长,是因为服务器的u比本地测试的u的主频低,但是核心却是本地u的4倍。

这样一来,其实整体性能会随着服务器的数量的添加而增加,根据业务需求而定吧,就说目前某度云的视频转换最高请求也就是几千左右,如果真有那个量级,傻瓜式的增加服务器就行了。

 

本系列完,感谢阅读