在Linux / Mono上运行ServiceStack的最佳方法是什么?

48

ServiceStack网站上列出,它显示ServiceStack可以在Mono上运行,其中有:

  • XSP
  • mod_mono
  • FastCgi
  • Console

这些不同的配置是什么,哪个更适合在Mono上进行Web服务?

5个回答

84

Linux更新

v4.5.2发布版 开始,ServiceStack支持.NET Core,它比基于共享跨平台代码库的Mono具有显著的性能和稳定性改进,并得到了微软团队的支持。如果您当前正在使用Mono运行ServiceStack,则强烈建议升级到.NET Core以充分利用其卓越的性能、稳定性和全面支持的技术栈。

Mono更新

我们推荐在Linux和Mono上托管ASP .NET站点的设置是使用nginx/HyperFastCgi。我们已经发布了一份逐步指南,介绍如何从头开始创建一个Ubuntu VM,并附带部署/安装/配置/初始化脚本,网址为mono-server-config

我们注意到了几个稳定性和性能问题,因此不再推荐使用MonoFastCGI。这篇博客文章提供了对Mono中不同ASP.NET托管选项的性能、内存使用和稳定性的良好分析。

开发

XSP类似于VS.NET WebDev服务器,是用C#编写的简单独立ASP.NET WebServer。这适用于开发或小工作负载。您只需从ServiceStack ASP.NET主机的根目录运行它,它就可以在http://localhost:8080上使用。

生产

对于外部互联网服务,通常希望将ServiceStack Web服务作为完整功能的Web服务器的一部分进行托管。Linux上最流行的两个完整功能的Web服务器是:

Nginx

使用Mono FastCGINginx中托管ServiceStack ASP.NET主机。

Apache

使用mod_monoApache HTTP Server中托管ServiceStack ASP.NET主机。

自托管

ServiceStack还支持自托管,这使您可以在独立的控制台应用程序中运行ServiceStack Web服务(即没有Web服务器)。当您不需要完整功能的Web服务器时,这是一个好主意(例如:您只需要在Intranet上内部托管Web服务)。

默认情况下,相同的ServiceStack控制台应用程序二进制文件在Windows/.NET和Mono/Linux上原样运行。但是,如果您希望,您可以轻松地将应用程序守护程序化,以按此处所述作为Linux守护程序运行。维基页面还包括有关配置自托管Web服务在Nginx或Apache反向代理后运行的说明。

由于它提供了与Heroku并发模型的良好匹配如其12因素应用程序所述,因此我们将在不久的将来寻求提供更多关于自托管的支持。

ServiceStack.net Nginx / Mono FastCGI配置

servicestack.net网站本身(包括所有实时演示)运行在Ubuntu hetzner vServer上,使用Nginx + Mono FastCGI。

该命令用于启动FastCGI后台进程:

fastcgi-mono-server4 --appconfigdir /etc/rc.d/init.d/mono-fastcgi 
  /socket=tcp:127.0.0.1:9000 /logfile=/var/log/mono/fastcgi.log &

这个主机托管了所有在/etc/rc.d/init.d/mono-fastcgi文件夹中定义为*.webapp文件的应用程序,使用XSP的WebApp文件格式进行指定,例如:

ServiceStack.webapp:

<apps>
<web-application>
        <name>ServiceStack.Northwind</name>
        <vhost>*</vhost>
        <vport>80</vport>
        <vpath>/ServiceStack.Northwind</vpath>
        <path>/home/mythz/src/ServiceStack.Northwind</path>
</web-application>
</apps>

这将在后台运行FastCGI Mono进程,您可以通过将以下规则添加到nginx.conf中来让Nginx连接它:
location ~ /(ServiceStack|RedisAdminUI|RedisStackOverflow|RestFiles)\.* {  
   root /usr/share/nginx/mono/servicestack.net/;  
   index index.html index.htm index.aspx default.htm Default.htm;  
   fastcgi_index /default.htm;
   fastcgi_pass 127.0.0.1:9000;  
   fastcgi_param SCRIPT_FILENAME /usr/share/servicestack.net$fastcgi_script_name;
   include /etc/nginx/fastcgi_params;  
}

该配置将转发任何以 /ServiceStack/RedisAdminUI 开头的路由到 FastCGI mono 服务器进程进行处理。一些使用此方式托管的示例应用程序包括:

对于那些有兴趣的人,servicestack.net的完整Nginx + FastCGI配置文件可供下载


19

我们在生产环境中使用nginx和unix文件套接字

我们发现在使用nginx、服务堆栈和mono进行套接字通信时存在一个bug/内存泄漏问题。虽然预计会出现cpu和内存的峰值,但它却从未再降下来过。我们没有做进一步的测试来发现问题所在,但是已经有一个类似于我们遇到问题的xamarin bugzilla

我们尝试了以下操作,对我们来说已经足够好了:

我们切换到使用unix套接字,并使用以下命令参数:

fastcgi-mono-server4 /filename=/tmp/something.socket /socket=unix /applications=/var/www/

我们使用这种方法遇到的问题是,每次运行fastcgi-mono-server4时socket文件的权限都会改变,因此您必须在启动fastcgi-mono-server4后更正它们!另一个缺点是,在我们的服务器上,它只能处理大约120个并发请求。但是目前对我们来说这并不是问题,您总是可以生成更多的进程。

希望这可以帮助到您。


太棒了,谢谢分享!你能在运行fastcgi-mono-server4后立即修复权限吗?如果可以的话,请在你的回答中包含这个步骤。 - mythz
是的,您可以在运行fastcgi-mono-server4后直接修复权限。要开始,您可以在/tmp/something.socket上执行chmod 777,但显然不要在生产环境中这样做!实际上,nginx和fastcgi-mono-server4都需要写入/tmp/something.socket的权限。 - Antony Denyer
很好的答案,看完后我尝试在我的生产服务器上实现,并通过使用相同的用户运行nginx和fastcgi-mono-server4(例如:wwwdata)成功处理了权限问题。谢谢。但是我不太明白如何通过生成更多进程来处理更多并发请求(您是否意味着在其他机器上运行并将nginx作为负载均衡器放在前面?)。 - Anton Hasan
@AntonHasan 当你使用nginx和fastcgi时,实际上是将所有请求代理到fastcgi进程中。Nginx不会自动为您生成新的进程。这就是为什么您需要运行fastcgi-mono-server4的原因。但是,基本上您需要将nginx作为负载均衡器运行。您可以在单个框中实现此目的,但是您是正确的,最好在前端使用ha代理/nginx,然后在后端使用多个服务器。希望这可以帮助到您。 - Antony Denyer
Unix域套接字通常比TCP套接字表现更好,但会限制您在本地机器之外扩展的能力:https://dev59.com/HnVC5IYBdhLWcg3wjx1d - Jonathan Oliver

6

免责声明:我是HyperFastCgi服务器的作者,并且我在ceco的答案中提到了博客文章的作者。

nginx搭配HyperFastCgi可以完成这项工作。与mono fastcgi服务器相比,HyperFastCgi不会泄漏内存,并且执行速度更快,因为它使用低级别的mono API在应用程序域之间传递数据,而不是采用跨域调用的缓慢mono JIT实现。此外,它还有一个选项,可以使用本地libevent库进行套接字通信,大约比当前的mono System.Net.Sockets实现快1.5-2倍。

HyperFastCgi的主要功能:

  • 允许使用3种不同的方式来处理套接字和跨域通信:
    • Managed Listener with Managed Transport(仅使用托管代码,异步System.Net.Sockets。由于JIT跨域调用缓慢,在mono中速度较慢)
    • Managed Listener with Combined Transport(使用异步System.Net.Sockets作为侦听器和低级别的mono API进行跨域调用。速度非常快)
    • Native Listener(使用本地libevent作为套接字库和低级别的mono API进行跨域调用。性能最好)
  • 允许使用线程池、.NET 4.5任务或单线程多种方式并行处理网络请求。与Native Listener组合使用的最后一个选项使Web服务器像NodeJS一样工作:所有请求都在单个线程中以异步方式处理。
  • 允许编写简单的请求处理程序,而无需使用System.Web。这将使请求的处理性能提高2-2.5倍。

3
这里有一篇关于使用ServiceStack的Mono性能的博客文章,对于那些即将决定如何托管服务的人可能会有帮助:Servicestack performance in Mono
正如文章中所说 - FastCGI Mono服务器存在大量内存泄漏问题,我可以证实。我在Ubuntu Desktop 14.04上使用Mono 3.2.8和Nginx 1.4.6以及FastCGI Mono Server 3.0.11运行了ab -n 100000 -c 10 http://myurl测试,并使用了ServiceStack 3.9.71编写了一个服务。我认为使用哪个版本的ServiceStack并不重要,因为FastCGI Mono Server是有问题的。它耗尽了所有可用的内存 - 总共约1GB的2GB。
另外,与其他解决方案相比,Nginx + FastCGI Mono Server的性能很差。我的示例REST服务每秒大约只有275个请求。博客的作者曾经审查过FastCGI Mono Server的代码并决定编写自己的实现。由于某种原因,在我的机器上它没有工作。
所以,我想说的是,你不应该使用FastCGI Mono服务器。除非你想经常重新启动你的服务器。
由于这篇文章大多数是负面内容,我应该说一下我关于托管服务的意图。我可能会选择使用继承AppHostHttpListenerLongRunningBase的AppHost在Nginx后进行自托管。使用上述相同的示例REST服务,我每秒可以获得约1100个请求。更好的消息是,该过程没有明显的内存泄漏问题。我进行了大约100万次请求的测试,该过程仅消耗了不到100MB的RAM。
附:我不是博客文章的作者 :)

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接