- PVSM.RU - https://www.pvsm.ru -

Как ServiceStack помогает поставить разработку веб-сервисов на поток

На хабре незаслужено обойден вниманием замечетальный .Net-фреймворк ServiceStack. Упомянут он очень кратко, в одной лишь статье [1], и то косвенно, мельком, и в самом конце, и упомянута там лишь мизерная его часть [2]. Очевидно, это связано с тем, что основная масса .Net-разработчиков использует стандартные решения от Microsoft для решения задач по разработке веб-сервисов и веб-приложений, а именно ASP.Net MVC/WebAPI или WCF и не заморачивается. Как мы попытаемся показать в этой статье, современный .Net хорош далеко не только своими стандартными технологиями.

Как ServiceStack помогает поставить разработку веб сервисов на поток

Если интересно, прошу под кат.

Итак, мы восполним этот пробел настоящей обзорной статьей, и в конце попробуем что-нибудь сваять своими руками с использованием данного инструмента, который сами в своей [3] практике [4] успешно используем, и, должны сказать, весьма довольны.

ServiceStack? Не, не слышал...

Для начала ответим на вопрос, чем является собственно ServiceStack. Это полноценный фреймворк для создания веб-сервисов и веб-приложений, вобравший в себя лучшее из мира C# и ASP.Net, и – да, вы угадали! – избавившийся от всего худшего, лишнего и ненужного. Однако, дорогой читатель, предупредим сразу, холивара не будет, не в этот четверг и не с нами! Забегая вперед, отметим, что существуют архитектурные вариации, соединяющие в единую систему компоненты, написанные и на ServiceStack (в роли сервера) и, к примеру, на ASP.Net MVC (в роли клиента).

Фреймворк зародился в недрах компании BBC, в то время, когда там работал Демис Беллот [5]. Началом развития фреймворка можно считать 2007 год, когда BBC, использующая стандартные Enterprise-решения от Microsoft в купе с водопадным подходом к разработке в условиях быстроизменяющихся требований попала прямиком в просак, причем “просак” более близкий к определению, данному героем Никиты Мигалкова из фильма “Жмурки”, нежели к определению из Толкового Словаря*.

Просак этот заключался в том, что для внесения каждого небольшого изменения было необходимо проходить цикл от UML до кода, который у них занимал до нескольких дней, всяческих костылях для совместимости форматов между старыми записями и новыми, и недельных простоях между мажорными релизами.

Комманда поставила перед собой простой вопрос: чем же все-таки является сервис? Вопрос в принципе не сложный, и многие из нас дадут на него те же самые ответы, а именно:

  • Это НЕ способ навязать конкретную платформу или технологию
  • Это НЕ способ навязать заранее определенные ограничения
  • Это НЕ повод [вечно] использовать заранее определенный формат или следовать заранее определенной архитектуре
  • Это предоставление услуг, а если говорить техническим языком, инкапсуляция некоторых возможностей, которые могут быть использованы повторно, и организация их доступности
  • Организация их доступности как можно большему числу клиентов, самым простым и эффективным способом, с минимальными затратами и максимальной возможностью повторного использования

Это то, чем является сервис по определению. В добавок к этому хороший сервис должен быть располагающим к предстоящим изменениям, должен быть спроектирован так, чтобы внесение изменений не было проблемой.

Размышления над этим вопросом привели к рождению ServiceStack, который позволил всего-лишь половине команды достигать больших результатов, чем вся команда прежде.

И все же, чем он лучше?

  • Более интуитивен и прост в использовании
  • Более высокая скорость работы по сравнению со стандартными .Net-решениями
  • Позволяет даже при не самых прямых руках достигать высокого уровня повторного использования кода

По поводу последнего пункта, следует, конечно же, сделать оговорку, что при наличии прямых рук высокого уровня повторного использования кода вполне можно добиться и при использовании стандартных решений от Microsoft. Однако, для этого требуются, опять же, и прямые руки, и правильный подход, и опыт. Благодаря простоте и сравнительной гениальности архитектуры ServiceStack менее квалифицированные разработчики могут достигать лучших результатов, а также воспитывать в себе приверженность к более эффективным подходам в структурировании кода.

И, наверное, для некоторых следующий момент будет и вовсе решающим:

Как ServiceStack помогает поставить разработку веб сервисов на поток

ServiceStack проекты могут развертываться на Linux прямо из коробки!

Таким образом вам не обязательно даже оплачивать дороговатый Windows Azure или, что еще накладнее, содержать собственный Windows Server. Для средного по величине проекта может сгодиться и обычный сервер, скажем, с Debian или Ubuntu Server, или даже VPS от Hetzner за $30 в месяц [6]. Для небольших проектов пойдет и cамый дешевый VPS за 10$ на Hetzner [7] или даже за 5$ на Digital Ocean [8].

Наши партнеры имеют опыт развертывания и хостинга [9] ServiceStack-проектов на Linux при помощи nginx + FastCGI Mono, и если нам всем это интересно, если мы их дружно попросим, я думаю, они не откажут нам в том, чтобы рассказать на хабре о том, как это делается в деталях.

А можно больше технических деталей?

Нельзя. Разработчики ServiceStack не стали рушить весь ASP.Net на корню, чтобы строить новое. Корень – а именно IHttpHandler – они оставили. Однако, все, что идет далее так и разрушили и использовали более легковесные альтернативы, которые местами сами немного адаптировали специально для решения задач разработки веб-сервисом. Фреймворк предоставляет свой кэш-менеджер, свои провайдеры аутентификации и сессии и даже предлагает своего MQ-брокера, работающего на базе Redis. Кстати, в рамках фреймворка также создан собственный Redis-клиент [10], который, на мой личный взгляд, просто шикарен, и он может быть использован отдельно от фреймворка в различных контекстах. В качестве штатного IOC-контейнера используется слегка модифицированная версия [11] достаточного популярного легковесного контейнера Func [12]. Правда, вместо него можно использовать и любой другой IOC-контейнер из множества доступных.

Краегоульным камнем ServiceStack являются DTO (Data Transfer Objects, Объекты Передачи Данных), которые базируются на плоских объектах POCO. Провайдеры аутентификации и сессии, также как и пользовательские сервисы базируются на POCO, что позволяет использовать различные бэкенды для различных реализаций. Из коробки доступны, к примеру, типизированные сессии для хранения непосредственно в памяти и в Redis. Также доступна и нетипизированная сессия для любителей динамизма, но она, к сожалению, работает несколько медленнее.

Подробно рассматривать архитектуру фреймворка в рамках одной статьи, к сожалению, нереально, но при наличии интереса со стороны любознательных, мы могли бы в будущем написать об этом серию статей. А пока что напишем небольшой HelloWorld чтобы подразнить аппетит читателя.

Хорош лить воду, давай коду!

Итак, для того, чтобы создать веб-сервис в ServiceStack-проекте необходимо сделать четыре простые вещи, а именно:

  • Создать класс для DTO запроса к сервисы
  • Создать класс для DTO ответа сервиса
  • Создать класс самого сервиса, отнаследовав его от базового класса, и переопределив методы, одноименные с HTTP-методами, которые вам необходимо реализовать
  • Наслаждаться жизнью и получать профит (шутка… хотя, нет, не шутка)

Давайте напишем простой сервис.

Создаем новый проект в Visual Studio или Xamarin Studio. За неимением первого под рукой, я воспользуюсь вторым, благо, под Mono все шикарно работает (а изначально для нас этот фактор и вовсе был решающим). И в качестве компенсации за неиспользование лучшей IDE, мы вам покажем как этот сервис задействовать из мобильного приложения для лучшей мобильной ОС.

Итак, создаем пустой ASP.Net-проект (Empty Web Application). Решение мы назовем SSHelloWorld, а проект – SSHelloAPI.

По проекту в Обозревателе Решения (Solution Explorer) делаем правый клик, и выбираем пункт “Управление пакетами NuGet” (Manage Nuget Packages).

Как ServiceStack помогает поставить разработку веб сервисов на поток

После того, как вы кликнете по кнопочке “Добавить” (Add), вас спросят, согласны ли вы с лицензионным соглашением? Ну т.к. русскоязычные пользователи читают лицензионные соглашения быстрее всех, мы соглашаемся, и к нашему проекту подключаются скачанные dll-ки ServiceStack'a.

Если в вашем проекте отсутствует Global.asax (а по идее должен отсутствовать), добавьте его и скопируйте в Global.asax.cs следующий код вместо того, что там есть:

using System;
using System.Collections;
using System.ComponentModel;
using System.Web;
using System.Web.SessionState;
using ServiceStack;

namespace SSHelloAPI
{
	public class Global : System.Web.HttpApplication
	{

		public class AppHost : AppHostBase
		{
			public AppHost() : base("Hello API", typeof(HelloService).Assembly) {}
		

			public override void Configure (Funq.Container container)
			{

			}
		}

		protected void Application_Start (Object sender, EventArgs e)
		{
			new AppHost ().Init ();
		}
	}
}

Не обращайте внимания на подсвечивание ошибок в коде сейчас. Нам нужно создать класс, в котором будет находиться наш сервис.

Также скорее всего придется вручную создать файл web.config. И весь его код должен быть заменен следующим:

<?xml version="1.0"?>
<configuration>
	<system.web>
	  <httpHandlers>
	    <add path="*" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*"/>
	  </httpHandlers>
	</system.web>

	<!-- Required for IIS 7.0 (and above?) -->
	<system.webServer>
	  <validation validateIntegratedModeConfiguration="false" />
	  <handlers>
	    <add path="*" name="ServiceStack.Factory" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
	  </handlers>
	</system.webServer>
</configuration>

Ну и, наконец, создадим новый файл HelloService.cs, в котором у нас будут три класса:

using System;
using ServiceStack;

namespace SSHelloAPI
{
	[Route("/hello")]
	[Route("/hello/{Name}")]
	public class HelloRequest
	{
		public string Name { get; set; }
	}
        
	public class HelloResponse 
	{
		public string Result { get; set; }
	}

	public class HelloService : Service
	{
		public object Any(HelloRequest request)
		{
			return new HelloResponse { Result = "Hello, " + request.Name };
		}
	}
	
}

Все просто и понятно, такой код мне даже стыдно комментировать. Компилируем и запускаем наш проект, и в адресной строке браузера введем после имени хоста и порта “/hello/Habrauser”. ServiceStack по заголовку запроса сам определяет тип клиента, и в данном случае покажет нам ответ сервиса в html-обертке. И в поле Result мы увидим, как сервис приветствует нас.

Название метода Any говорит о том, что мы определили одну и ту же логику для всех HTTP-методов.

Обратите внимание на страничку metadata, которая открывается первым делом при запуске проекта. Она содержит автоматически сгенерированную документацию к сервисам. Как видите, ServiceStack на ходу создает различные конечные точки, и мы можем работать с нашим сервисом как с RESTful-сервисом, так и как с SOAP-сервисом (да, я имею в виду именно SOAP, дорогой читатель).

Как ServiceStack помогает поставить разработку веб сервисов на поток

Сервис, конечно, скучный, но дабы не перегружать статью мы не стали сразу включать более сложные примеры. Однако, он дает почувствовать вкус SericeStack и если вам были интересно, то теперь – с нами или без нас – вы можете отведать больше.

Как ServiceStack облегчает жизнь мобильному разработчику

Еще чем хорош ServiceStack, так это тем, что созданный сервис весьма удобно использовать в Windows Phone, Xamarin.iOS или Xamarin.Android-приложении (правда, для последних двух необходима бизнес-лицензия на Xamarin). Существуют различные способы, но самый простой (однако, не самый красивый), это выделить в отдельные файлы классы Запросов и Ответов, и подключить их через связывание в проект мобильного приложения. Также из Nuget установить сборку ServiceStack.Client.

Далее, допустим, на событие нажатия кнопки вешаем такой обработчик:

			button.TouchUpInside +=  (object sender, EventArgs e) => {
				try {
					var client = new JsonServiceClient("http://127.0.0.1:8080");
					HelloResponse response = client.Get<HelloResponse>(new HelloRequest() { Name = "iPhone" });
					resultLabel.Text = response.Result;
				}
				catch (Exception ex)
				{
					resultLabel.Text = ex.Message;
				}
			};

Более подробно этот вопрос также можно рассмотреть в будущем.

А что с лицензией?

Начиная с версии 4.0 проект обрел коммерческий окрас. Ну, а почему бы и нет, если это делает ешл лучше? Исходные коды фреймворка по-прежнему остаются открытыми, однако, лицензия позволяет использовать фреймворк бесплатно лишь для небольших проектов со следующими ограничениями:

  • 10 операций (т.е. 10 DTO запросов)
  • 10 Таблиц в OrmLite
  • 20 Типов с JSON, JSV и СSV-сериализаторами
  • 20 Типов для Redis-клиента
  • 6000 запросов в час к Redis

Ну и ладно, не Redis'ом единым, кроме OrmLite есть и другие ORM, а вот 10 операций — это уже существенное, конечно, ограничение.

Более подробная информация о лицензировании и ценах доступна на этой страницe [https://servicestack.net/pricing].

На данный момент мы пользуемся в наших проектах 3й версией, которая доступна под лицензией BSD, и переход на 4ю только рассматриваем. Если не хотите быть привязанными к “коммерческой стороне” можете спокойно брать 3ю ветку и использовать ее в своем проекте, она вполне зрелая и стабильная.

Ссылки и сноски

ПРОСАК (Толковый Словарь Даля) м. новг. твер. прядильня; крутило, канатный, веревочный стан, на котором сучат, спускают веревки. || *Затруднительное положение, бедушка, где не знаешь, как быть. Он впросак попал, сидит впросаках. Просак (от сучить?), пространство от прядильного колеса до саней, где снуется и крутится бичевка, спускается вервь; если попадешь туда концом одежи, волосами, то скрутит, и не выдерешься; от этого поговорка.

А если серьезно, то вот они:

Официальный сайт
servicestack.net [13]

Вики
github.com/ServiceStack/ServiceStack/wiki [14]

Слайдшоу с презентацией Демиса Беллота о ServiceStack
www.slideshare.net/newmovie [15]

Некоторые примеры рабочих проектов (код открыт и доступен на github)
Аналог imgur
imgur.servicestack.net [16]

RestMovies
mono.servicestack.net/ServiceStack.MovieRest/ [17]

Аналог StackOverflow
mono.servicestack.net/RedisStackOverflow/ [18]

И многие другие примеры доступны на этой странице [19], а их исходники на github [20].

И если тебе, дорогой читатель, стало интересно и ты жаждешь узнать большего, ты только скажи, и мы — общими усилиями — с удовольствием продолжим развивать и раскрывать тему.

Автор: samujan

Источник [21]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/ios/55551

Ссылки в тексте:

[1] статье: http://habrahabr.ru/post/133778/

[2] часть: https://github.com/ServiceStack/ServiceStack.Text/

[3] своей: http://habrahabr.ru/post/212873/

[4] практике: http://zakaz.mobedu.ru/?utm_source=HabraHabr&utm_medium=post&utm_term=habrapost&utm_content=ad_post&utm_campaign=HabraPost

[5] Демис Беллот: https://twitter.com/demisbellot

[6] VPS от Hetzner за $30 в месяц: http://www.hetzner.de/en/hosting/produkte_vserver/vq19

[7] VPS за 10$ на Hetzner: http://www.hetzner.de/en/hosting/produkte_vserver/vq7

[8] за 5$ на Digital Ocean: https://www.digitalocean.com/pricing

[9] хостинга: https://www.reg.ru/?rlink=reflink-717

[10] собственный Redis-клиент: https://github.com/ServiceStack/ServiceStack.Redis

[11] слегка модифицированная версия: https://github.com/ServiceStack/ServiceStack/wiki/The-IoC-container

[12] легковесного контейнера Func: http://funq.codeplex.com

[13] servicestack.net: http://servicestack.net

[14] github.com/ServiceStack/ServiceStack/wiki: https://github.com/ServiceStack/ServiceStack/wiki

[15] www.slideshare.net/newmovie: http://www.slideshare.net/newmovie

[16] imgur.servicestack.net: http://imgur.servicestack.net

[17] mono.servicestack.net/ServiceStack.MovieRest/: http://mono.servicestack.net/ServiceStack.MovieRest/

[18] mono.servicestack.net/RedisStackOverflow/: http://mono.servicestack.net/RedisStackOverflow/

[19] этой странице : https://servicestack.net/features

[20] их исходники на github: https://github.com/ServiceStack/ServiceStack.Examples

[21] Источник: http://habrahabr.ru/post/213389/