Пишу веб-проекты в visual studio, и с каждой новой версией студии она как будто затачивается для работы с Windows Azure. Мне нравится Азура, хотя я пользуюсь только небольшим набором возможностей. Основное для меня — это Облачная служба. Облачная служба отлично подходит для разворачивания распределенного сервера.
Итак, я создаю облачную службу, в которую добавляю одну веб-роль (виртуальная машина с IIS), один воркер (виртуальная машина без IIS) и общую библиотеку классов. После публикации моим ролям присваивается ip-адрес и разные порты. То есть сразу есть tcp сеть, ручные настройки минимальны и могут делаться в самой студии. Можно, к примеру, сделать общедоступную точку доступа для воркера, но мне это не нужно. Мой воркер будет скрыт от внешних глаз и на нём будет висеть wcf-сервер, а общаться мои роли будут по быстрой локальной сети.
Общие классы я выношу в библиотеку (которую подключаю ко всем ролям), к примеру, интерфейс и канал связи:
[ServiceContract]
public interface IwcfChat
{
[OperationContract]
string SendMessage(string userId, string userName, string text);
[OperationContract]
string GetMessages(string userId, string userName);
}
//================
public sealed class wcfChat:IDisposable
{
IwcfChat _channel;
ChannelFactory<IwcfChat> factory = null;
public wcfChat()
{
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.None;
b.Security.Message.ClientCredentialType = MessageCredentialType.None;
#if(DEBUG)
EndpointAddress address = new EndpointAddress("net.tcp://127.255.0.1:9003/wcfChat");
#else
EndpointAddress address = new EndpointAddress("net.tcp://"+spr.wcfIP+":9003/wcfChat");
#endif
factory = new ChannelFactory<IwcfChat>(b, address);
factory.Faulted += OnChannelFaulted;
factory.Open();
}
public IwcfChat channel
{
get
{
if (factory != null && factory.State == CommunicationState.Opened)
{
if(_channel==null) _channel = factory.CreateChannel();
return _channel;
}
return null;
}
}
void OnChannelFaulted(object sender, EventArgs e)
{
factory.Abort();
}
public void Dispose()
{
factory.Close();
}
}
Методы в веб-роли вызываю так:
using (var chat = new wcfChat())
{
res = chat.channel.SendMessage(id, name, text);
}
Соответственно, в воркере у меня реализация методов из интерфейса (SendMessage, GetMessage), не буду их расписывать, а так же в воркере при старте выполняется код, который делает его хостом для wcf:
public override bool OnStart()
{
// Задайте максимальное число одновременных подключений
ServicePointManager.DefaultConnectionLimit = 12;
// Create the host
ServiceHost host = new ServiceHost(typeof(wcfChat));
// Read config parameters
string hostName = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["port"].IPEndpoint.Address.ToString();
int port = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["port"].IPEndpoint.Port;
int mexport = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["mexport"].IPEndpoint.Port;
// Create Metadata
ServiceMetadataBehavior metadatabehavior = new ServiceMetadataBehavior();
host.Description.Behaviors.Add(metadatabehavior);
Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
string mexendpointurl = string.Format("net.tcp://{0}:{1}/wcfChatMetadata", hostName, 8003);
host.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, mexendpointurl, new Uri(mexendpointurl));
// Create end point
string endpointurl = string.Format("net.tcp://{0}:{1}/wcfChat", hostName, 9003);
host.AddServiceEndpoint(typeof(IwcfChat), new NetTcpBinding(SecurityMode.None), endpointurl, new Uri(endpointurl));
// Open the host
host.Open();
// Trace output
Trace.WriteLine("WCF Listening At: " + endpointurl);
Trace.WriteLine("WCF MetaData Listening At: " + mexendpointurl);
return base.OnStart();
}
Тут я показал методы типа string, но тип возвращаемого значения может быть абсолютно любой, к примеру, сложный класс, который описан в моей общей библиотеке. Всё, никаких других настроек в вебконфигах, никаких упаковок в xml или SOAP у меня нет. Нет автоматически генерируемых файлов контрактов. Когда я пытался это сделать, в интернетах при поиске информации про wcf всегда всплывает настройка под http со всеми этими упаковками/распаковками. Да, wcf технология изначально придумана для связи разнородных систем, где необходимо сериализовать и передавать как строку. Но если у нас один язык программирования, а клиент и сервер wcf — это всё наша разработка, то не нужно городить огород, всё прекрасно работает.
Таким образом у меня получается распределенный сервер, для затратных операций я делаю отдельный воркер, тут, к примеру, показан чат. Все функции чата вынесены в отдельную виртуальную машину и я могу увеличивать производительность как самого сайта (веб-роли), так, отдельно, и чата.
Такая архитектура мне кажется правильной и может выдержать более сильную нагрузку, чем монолитный проект. Так же всё это разрабатывается и отлаживается как один проект в студии, то есть при вызове метода по wcf я могу в отладке пройти глубже в код, без сообщений типа «внутри отлаживать я не могу, не знаю что там происходит, вот такой вернулся результат».
С Азуровскими инструментами это делается всё легко и просто, я запускаю весь проект одной кнопкой и отлаживаюсь по нему как по одному проекту. Я помню когда-то давно, на одном из проектов была похожая архитектура, но я был молод, и мне там было очень сложно: какие-то фасады, и, если параметры у метода менялись, я изменения в четырёх местах вносил.
Мне нужно нечто подобное сделать на обычных серверах. Не на своих физических серверах, а на vds/vps виртуалках у какого-нибудь обязательно российского хостера. Я нашел забавную технологию у одного из хостеров (1gb.ru), называется ресурс Windows Azure Pack / COSN. По описанию это урезанная версия Азуры и всё должно было бы «взлететь». Конечно же, у них есть пробный период, я посмотрел. В браузере управление как-будто из старой версии портала Азуры (если кто помнит). Из возможностей есть только создание виртуальных машин, объединение их в сеть (вручную), есть service bus — и всё. Так же нет возможности загрузить эту подписку в студию, а в этом и есть многое из удобств. Плюс нет возможности создания облачной службы. В описании сказано, что это «частное облако» будет дорабатываться и дополняться возможностями с оригинальной Азуры, но поддержка сказала, что всё уже давно заморожено, и вообще, это несовместимые технологии («этот Azure Pack совершенно по смыслу не совместим с настоящим Azure. Там что есть, то есть, и есть там маловато. Идеи там общие, но реализация разная совершенно, API разные и так далее.» (с))
В общем, если я арендую у
Собственно, статью я написал, потому что потратил очень много времени на организацию такой архитектуры, и, надеюсь, она поможет еще кому-то.
Как такую штуку перенести на обычный
Еще я наткнулся на создание wcf службы и её публикацию, всё быстро и просто, но смысл там тот же самый: публичный http с сериализаций/десериализацией, мне такое не подходит.
Автор: Jeer