Agora que vocês já sabem o que são filas (ou queues), vou contar aqui como utilizá-las, com código. Vou seguir com um exemplo extremamente simples, presente no próprio Azure Services Training Kit. Se você não viu ainda nada de Azure Storage, recomendo dar uma olhada antes. Aqui no blog tem bastante coisa.

Queues funcionam assim: você abre um projeto qualquer, adiciona as referências do Azure, no caso a do Sample de storage do SDK que já mencionei antes, o StorageClient, e o do Astoria. Isso é tudo que precisamos. Então cria uma obtém uma fila, cria uma mensagem e a envia. Simples assim.

O código abaixo coloca um texto simples de uma fila chamada "messages". O texto vem do textbox "txtMessage", como pode ser visto na penúltima linha. A fila é criada antes se não existe (veja chamadas a "DoesQueueExist" e "CreateQueue").

            StorageAccountInfo account = new StorageAccountInfo(
                baseUri,
                null,
                accountName,
                accountKey);

            QueueStorage service = QueueStorage.Create(account);

            MessageQueue queue = service.GetQueue("messages");

            if (!queue.DoesQueueExist())
            {
                queue.CreateQueue();
            }

            Message msg = new Message(txtMessage.Text);
            queue.PutMessage(msg);

Isso é tudo para colocar uma mensagem na fila. E para tirar? Simplificando um pouco, é o que está abaixo. Note que ele cria a conta também, verifica se a fila existe, e então puxa uma mensagem. Se a mensagem existe ele a escreve no log do RoleManager. Simples assim. Depois disso seria somente verificar novamente após algum intervalo, e fazer isso infinitamente. É por isso que o trabalho se encaixa bem no worker role do Azure.

            StorageAccountInfo account = new StorageAccountInfo(
                baseUri,
                null,
                accountName,
                accountKey);

            QueueStorage service = QueueStorage.Create(account);

            MessageQueue queue = service.GetQueue("messages");
            
            if (queue.DoesQueueExist())
            {
                Message msg = queue.GetMessage();

                if (msg != null)
                {
                    RoleManager.WriteToLog("Information",
                        string.Format("Message '{0}' processed.", msg.ContentAsString()));
                    queue.DeleteMessage(msg);
                }
            }

Mais simples impossível, certo? Lembrando que a fila fica lá na nuvem, nos servidores da Microsoft. No fim das contas as chamadas são nada mais nada menos que chamadas REST.

Agora, e se eu quiser passar uma mensagem complexa? Bom, você sempre pode serializar objetos com XML, e, como todos sabemos, objetos são mensagens, e XML é texto. A partir daí é só se divertir. Enjoy!


Postado na(s) categoria(s) Azure pelo giovanni bassi em 31 de março de 2009 às 10:20 | Tags:

Já falei aqui de outros serviços do Azure, está na hora de falar de Queues, ou filas.

Filas são algo necessário por casusa da natureza do processamento distribuído, que sofre com a latência, e não teria escalabilidade se fosse fortemente consistente. Mais informações em um post que escrevi a alguns meses sobre ACID X Base, que são conceitos opostos para tratamento de atualizações. Entenda o seguinte se não quiser ler porque BASE é quase obrigatório em aplicações na nuvem: precisamos de filas.

E no Azure elas fazem parte do próprio SO, não são serviços adicionais, como o Workflow, ou o SDS.

Uma fila enfilera mensagens. As mensagens no Azure são strings, mas imagino que futuramente isso deve poder conter algum tipo de dado binário. As mensagens geralmente contém informações do tipo "atualize a tabela x com o valor y", ou "conte o total e atualize a coluna tal", ou ainda "mande um e-mail se o processamento x já terminou e ainda não teve o e-mail enviado". Uma fila pode ter mensagens de até 8KB, mas um número infinito de mensagens.

Queues funciona assim: Imagina que você tem dois fornecedores de fila, e eles enfileram 4 mensagens. Assim:

Início da fila

Temos também, como visto acima, dois consumidores de fila, C1 e C2, que vão buscar mensagens na fila. No caso acima, o C1 puxou uma mensagem da fila, a mensagem 1, por 30 segundos. Nestes 30 segundos a mensagem 1 está invisível na fila para todo mundo, mas ainda não foi excluída da fila.

Então o consumidor 2 puxa a mensagem 2 para ele, também por 30 segundos. O C1 ainda processa a mensagem 1. Assim:

Mensagens processadas

Aí o C2 termina de consumir a mensagem 2, e exclui ela da fila. Agora, mesmo o C2 quebrar, a mensagem 2 já foi processada e morreu. Assim:

Um consumidor terminou

Então o C1 cai por causa de algum bug ou outro problema. Ele ainda não tinha terminado de processar a mensagem 1. Então os 30 segundos passam, e a mensagem volta a aparecer na fila automaticamente. Assim:

Um consumidor caiu

Então o C2 vai puxar uma nova mensagem da fila, e puxa a primeira na ordem, que é a mensagem 1, que vai agora ser processada pelo C2. Assim:

Final do processamento

Dessa forma, a mensagem 1 tem garantia de processamento ao menos uma vez. O problema está nesse "ao menos". Isso significa que ela pode ser processada mais que uma vez? Significa. Quantas vezes? Impossível dizer. Programe-se para que ela possa rodar n vezes, sem deixar o sistema inconsistente. Como? Verificando se ela já rodou, ou algo do tipo. A mensagem pode ser ACID internamente, mesmo se for BASE para o serviço, não se esqueça disso.

Esse processo todo dá garantia de processamento se uma parte do sistema cair.

Ah, quem são os consumidores da fila? Geralmente vão ser worker roles do próprio Azure. Obrigatoriamente? Não, obvio que não. Poderia ser um serviço web? Poderia, mas acho que vai ser um cenário mais incomum.

No próximo eu continuo com exemplos de código, mas concretos.


Postado na(s) categoria(s) Azure pelo giovanni bassi em 25 de março de 2009 às 02:08 | Tags:

image Seguindo com um exemplo prático do Azure .Net Service Bus (NSB), depois de eu explicar um pouco do que ele é.

A programação do NSB é bem simples. Você começa criando uma interface de contrato e sua implementação, bem ao estilo WCF:

    [ServiceContract(Name = "EchoContract", Namespace = "nmsp")]
    public interface IEchoContract
    {       
        [OperationContract]
        string Echo(string text);
    }
    [ServiceBehavior(Name = "EchoService", Namespace = "nmsp")]
    public class EchoService : IEchoContract
    {
        public string Echo(string text)
        {
            Console.WriteLine("Echoing: {0}", text);
            return text;
        }
    }

Configura o app.config com os endpoints corretos no servidor (nesse caso é uma aplicação console):

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="cardSpaceClientCredentials">
          <transportClientEndpointBehavior credentialType="CardSpace" />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <netTcpRelayBinding>
        <binding name="default" />
      </netTcpRelayBinding>
    </bindings>
    <services>
      <service name="Service.EchoService">
        <endpoint name="RelayEndpoint"
          contract="Service.IEchoContract"
          binding="netTcpRelayBinding"
          bindingConfiguration="default"
          behaviorConfiguration="cardSpaceClientCredentials"
          address="" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

Neste caso o protocolo é via TCP (vejam o binding netTcpRelayBinding).

Aí você abre o serviço e espera, como qualquer serviço WCF:

        static void Main(string[] args)
        {
            string account = GetAccount();
            Uri address = new Uri(String.Format("sb://{0}/services/{1}/EchoService/", ServiceBusEnvironment.DefaultRelayHostName, account));
            ServiceHost host = new ServiceHost(typeof(EchoService), address);
            host.Open();
            Console.WriteLine("Service address: " + address);
            Console.WriteLine("Press [Enter] to exit");
            Console.ReadLine();
            host.Close();
        }

Perceberam que não há nada de diferente de um serviço comum WCF? A única diferença notável é o protocolo "sb:", que na prática é uma abstração que vira um "tcp:", ou um "http:". O resultado é isso aqui (clique para ampliar):

Servidor aberto

Vocês já devem ter percebido que a aplicação somente ecoa o que ela recebeu na mensagem, e escreve isso na janela do console. Nesse caso o servidor já havia ecoado duas mensagens.

No cliente é um pouco mais complicado que uma configuração WCF comum. Não tem "Add Service Reference…". É tudo na mão. Mas também é simples. Você reimplementa o contrato:

    [ServiceContract(Name = "EchoContract", Namespace = "nmsp")]
    public interface IEchoContract
    {
        [OperationContract]
        string Echo(string text);
    }
    public interface IEchoChannel : IEchoContract, IClientChannel { }

E abre e chama o serviço. O chato é ter que fazer na mão, abrindo ChannelFactory<T>, criando endereço, etc. Isso é um claro ponto para dar um monte de erros. Vamos ver se isso melhora um pouco até a versão final.

        static void Main(string[] args)
        {
            Console.Write("[Client] Enter the name of the user you want to connect with: ");
            string serviceUserName = Console.ReadLine();
            Uri serviceUri = new Uri(String.Format("sb://{0}/services/{1}/EchoService/", ServiceBusEnvironment.DefaultRelayHostName, serviceUserName));
            EndpointAddress address = new EndpointAddress(serviceUri);
            ChannelFactory<IEchoChannel> channelFactory = new ChannelFactory<IEchoChannel>("RelayEndpoint", address);
            IEchoChannel channel = channelFactory.CreateChannel();
            channel.Open();
            Console.WriteLine("Enter text to echo (or [Enter] to exit):");
            string input = Console.ReadLine();
            while (!String.IsNullOrEmpty(input))
            {
                try
                {
                    Console.WriteLine("Server echoed: {0}", channel.Echo(input));
                }
                catch (Exception e)
                {
                    Console.WriteLine("Error: " + e.Message);
                }
                input = Console.ReadLine();
            }
            channel.Close();
            channelFactory.Close();
        }

O resultado deve ser parecido com o que está abaixo (clique para ampliar). A cada vez que você manda uma mensagem, ela aparece na console do servidor e é ecoada de volta na janela do cliente:

Cliente no echo

Toda essa comunicação passa pelo servidor da Microsoft.

Vocês notaram uma menção ao cardspaces no arquivo de configuração? O cartão do cardspaces com acesso ao serviço é configurado online, como vocês podem ver abaixo. Além disso dá para usar certificado X.509 ou usuário e senha (basic auth).

Configurando o cardspaces online

Interessante, certo? E o legal é que você não precisa registrar nenhum serviço online no portal, como é feito para usar o Table Storage, por exemplo, ou até no Workflow Services. Se você está autenticado, você pode abrir um ponto de conexão no NSB e tudo vai funcionar. A página do NSB mostra isso tudo. No caso, meu projeto se chama "GiggioDotNet", e no portal do Azure você pode ver como configurar seus endpoints:

Portal do Azure - .Net Service Bus

Em resumo, bem fácil de usar. Dá para melhorar aqui e ali, mas o que estou vendo já está bem legal.


Postado na(s) categoria(s) Azure pelo giovanni bassi em 16 de março de 2009 às 10:17 | Tags: ,

Como havia avisado aqui, palestrei neste sábado sobre Windows Azure. Tinha bastante gente por lá, e eu falei por três horas sobre Azure, introduzindo a plataforma e depois falando um pouco mais concretamente de Azure Hosting, .Net Service Bus, Table Storage, Blobs e Queues. Dividi em 2 sessões para ninguém morrer de gangrena na perna, e na segunda sessão fiz muitas demos. O pessoal participou bastante, com várias perguntas interessantes. Eu achei que ia sobrar um tempinho para Q&A, mas se deixasse eu falava mais uma hora fácil. O feedback da palestra foi, com praticamente todas as notas ficando entre muito bom e ótimo. Excelente!

Agradeço o convite da Juliana Prado Uchôa, que é Microsoft Student Partner e lider do grupo Channel TI pelo convite.

Coloquei as apresentações da palestra no SlideShare. Seguem abaixo:


Postado na(s) categoria(s) Azure , Eventos pelo giovanni bassi em 16 de março de 2009 às 02:32 | Tags: ,

.Net Services No meio do Azure estão os .Net Services, que são uma série de serviços disponibilizados pela Microsoft na Nuvem. Na prática: Workflow, Service Bus e Access Control Services. Para saber mais recomendo o excelente post do Waldemir Cambiucci sobre o assunto.

Se você já leu ou já sabe o que é, então vou mostrar um pouco do que você pode fazer com o .Net Service Bus (NSB) neste post e no próximo. O NSB se propõe a ser um barramento entre uma ou mais aplicações, controlando e distribuindo o fluxo de informação. Ele se propõe a aplicar, inclusive, autenticação e autorização com ajuda do Access Control Services (que é um dos 3 serviços do .Net Services).

O diagrama abaixo, tirado da palestra de .Net Services do último PDC, mostra o que é possível fazer. Você possui uma aplicação que envia um dado, que bate em um endpoint, e vai parar no receptor, que fica esperando a mensagem. A comunicação pode passar sempre pelo servidor da Microsoft na Nuvem (aparecendo em flechas vermelhas), como também se conectar diretamente com o destino (mostrado em verde). Neste caso, a comunicação inicial passa pelo servidor da Microsoft e depois segue para a comunicação direta se ela estiver disponível (por isso a linha verde pontilhada).

One way

 

Também é possível realizar uma comunicação do estilo publisher/subscriber, ou seja, publicador e assinante, mais conhecida como multicast. Neste caso a mensagem segue para a nuvem, e é distribuída para todos os assinantes. E você pode ainda ter mais de um publisher:

Multicast

Achei esse recurso de Multicast é especialmente interessante, porque permite usar a infra-estrutura do Azure para fazer envios massivos de dados via web, sem se preocupar com a quantidade de assinantes.

Tudo isso é complicadíssimo de fazer. Não, mentira. É muito fácil. Chega a ser ridículo de tão fácil. Vou mostrar no próximo post como montar uma aplicação simples que manda dados, e vou explicar o que está acontecendo. E já adianto: se você conhece WCF, programar para o NSB é muito simples, porque os caras não reinventaram a roda, toda a codificação está sendo feita sobre o WCF, somente com a adição de novos tipos de binding. E como tudo é baseado em WCF (de longe a melhor tecnologia para distribuição de computação), você pode utilizar (e trocar de) protocolos com facilidade, usando TCP, HTTP. Há também suporte total para padrões como WS*, REST, SOAP, Atom, etc. Isso permite acesso a qualquer linguagem. Não bastasse isso a Microsoft está preparando bibliotecas de classes de conexão a todo o .Net Services não só para .Net, mas também para Java, PHP, Ruby, etc…

A parte de controle de acessos também ficou bem legal, e tenho certeza que será um motivo importantíssimo para a adoção, pelas capacidades de federação, que estão ficando muito facilitadas. Mas isso é assunto para outro post.

Em tempo: você vai precisar do SDK para desenvolver com .NET Services. Nesse momento, o último SDK é o de dezembro de 2008. E tudo funciona perfeitamente, sem bugs, nem parece CTP. Você vai precisar de uma conta do CTP para acessar, portanto mexa-se se você ainda não tem uma, porque elas demoram a chegar.


Postado na(s) categoria(s) Azure pelo giovanni bassi em 11 de março de 2009 às 03:13 | Tags: ,

A Microsoft está em fase Alpha com o Azure mesmo. Testando os blobs, todo o processamento passa por um projeto que eles criaram chamado "StorageClient", que faz parte do SDK. Imagino que até o lançamento, na verdade, espero que em um CTP futuro, já tenhamos um conjunto de bibliotecas mais padronizado.

De qualquer maneira, sigo fazendo vários testes, e posso dizer para vocês que o Blog Storage funciona perfeitamente. A API é bem simples. Os blobs no Azure são conteúdos binários, e são usados para armazenar qualquer arquivo que você quiser. Podem ser músicas, imagens, zips, o que você quiser.

Por exemplo, para criar o objeto de contêiner, você faz assim:

        private BlobContainer container;

        private BlobContainer GetContainer()
        {
            BlobStorage blobStorage = BlobStorage.Create(StorageAccountInfo.GetDefaultBlobStorageAccountFromConfiguration());
            BlobContainer newContainer = blobStorage.GetBlobContainer(RoleManager.GetConfigurationSetting("ContainerName"));

            newContainer.CreateContainer(null, ContainerAccessControl.Public);
            return newContainer;
        }

Muito simples, certo? Daí para obter os blobs do contêiner, chama um "ListBlobs", assim:

        private void RefreshGallery()
        {
          this.images.DataSource = this.container.ListBlobs(String.Empty, false);
          this.images.DataBind();
        }

Para apagar um blog é simples também:

                string blobName = (string)e.CommandArgument;
                if (this.container.DoesBlobExist(blobName))
                {
                    this.container.DeleteBlob(blobName);
                }

Para criar um blob, você pega um arquivo postado e uma strings de uns textboxes, e manda para o serviço, o arquivo como conteúdo, e o resto como metadados. A API continua muito simples (dei uma resumida):

 private void SaveImage(string id, string fileName, string contentType, byte[] data)
        {
            BlobProperties properties = 
                new BlobProperties(string.Format(CultureInfo.InvariantCulture, "image_{0}", id));
            NameValueCollection metadata = new NameValueCollection();
            metadata["Id"] = id;
            metadata["Filename"] = fileName;
            properties.Metadata = metadata;
            properties.ContentType = contentType;
            BlobContents imageBlob = new BlobContents(data);
            this.container.CreateBlob(properties, imageBlob, true);
        }

Subi algumas imagens. Os resultado é uma página web que fica simples, mas funciona:

Resultado dos testes

Se você for olhar na URL da imagem, vai ver que ela vem do serviço de blogs:

Imagem no Azure Blobs

Testei com arquivos grandes, e ele quebra o blob em vários "blocks", para permitir reenvio em caso de quebra de conexão, e não precisar reenviar o arquivo inteiro. Inteligente. Isso está no método PutBlobImpl, que reproduzo abaixo:

        private bool PutBlobImpl(BlobProperties blobProperties, Stream stream, bool overwrite, string eTag)
        {
            // If the blob is large, we should use blocks to upload it in pieces.
            // This will ensure that a broken connection will only impact a single piece
            long originalPosition = stream.Position;
            long length = stream.Length - stream.Position;
            if (length > ChunkingSize)
                return PutLargeBlobImpl(blobProperties, stream, overwrite, eTag);

            bool retval = false;
            RetryPolicy R = stream.CanSeek ? this.RetryPolicy : RetryPolicies.NoRetry;
            R(() =>
            {
                if (stream.CanSeek)
                    stream.Position = originalPosition;
                retval = UploadData(blobProperties, stream, length, overwrite, eTag, new NameValueCollection());
            });

            return retval;
        }

Viram também o sistema de retries, todo baseado em delegates e lambdas? Elegante, não?

Infelizmente os metadados não funcionam ainda com caracteres fora do ANSI, como acentos, cedilha, etc. Mas funcionam direito se você evitá-los.

Todos esses exemplos estão no Trainning Kit de Fevereiro, que você pega aqui. O material é bem legal e muito claro e direto.


Postado na(s) categoria(s) Azure pelo giovanni bassi em 9 de março de 2009 às 10:27 | Tags:

Segundo Steve Ballmer, até o PDC deste ano o Azure está lançado. Ele não diz se tudo estará no ar ou se só algumas partes, mas é um fato: até Novembro já termos a disposição a computação na nuvem, como se fosse água.

Quer dizer, os norte-americanos terão. Quando será que isso chega à terras tupiniquins?


Postado na(s) categoria(s) Azure pelo giovanni bassi em 4 de março de 2009 às 10:21 | Tags:

Muita gente tem comparado o Azure com o EC2 da Amazon. Se você olhar de perto vai ver que eles não são parecidos, eles seguem caminhos bem diferentes.

Qual das filosofias vai se provar melhor só o mercado vai dizer. A Microsoft está apostando pesadamente na idéia de que o sistema operacional está na nuvem, ao invés de simplesmente hospedar um servidor ou um banco de dados.

Em entrevista recente, Dave Cutler, do time do Azure, lembra que o Azure é feito de:

  1. Fabric Controller;
  2. Armazenamento;
  3. Ambiente de desenvolvimento integrado e emulado;
  4. Sistema operacional e virtualização.

Dos 4 itens, ele considera que o primeiro é que traz o diferencial, e que vai tornar o serviço atrativo.

Eu concordo plenamente. Qualquer empresa que se disponha a oferecer computação como se fosse um serviço, deve ser capaz de me dar tanto quanto eu precisar, imediatamente, de maneira segura e confiável. Não quero pedir um servidor a mais e ter que esperar um dia. Ou 4 horas. Aliás, não quero nem pedir, quero entrar numa interface web, clicar num botão e tudo acontece sozinho. Aliás, nem isso, quero que o próprio sistema se ajuste – aumentou a demanda, aumenta a vazão e me manda um SMS.

Eu não preciso ligar na cia de água se vou aumentar meu consumo em determinada semana, eu simplesmente uso a água a mais, e depois pago por ela. Se poder computacional virou commodity, é assim que tem que ser. Qualquer competidor que quiser jogar sério vai ter que jogar nestas novas regras.


Postado na(s) categoria(s) Azure pelo giovanni bassi em 3 de março de 2009 às 10:16 | Tags:

Dia 14/03, no segundo sábado a partir de hoje, estarei palestrando sobre Windows Azure e Cloud Computing na Livraria Cultura do Shopping Market Place (em frente ao Shopping Morumbi), em São Paulo. Serão na verdade duas palestras de uma hora e vinte, com um pequeno intervalo, totalizando 3 horas de apresentação. A entrada é gratuita.

Mais informações aqui.

Vejo vocês lá.


Postado na(s) categoria(s) Azure , Eventos pelo giovanni bassi em 2 de março de 2009 às 11:43 | Tags: , ,

Liberada uma atualização para o kit de treinamento do Azure. Você pega ela aqui. 141 Megas... ou seja, tem coisa lá.

Ganhamos:

  1. 19 walkthroughs para os serviços
  2. 10 apresentações cobrindo todo o Azure
  3. 3 hands-on labs a mais para o Live Services

Agora só não aprende Azure quem não quer. (ou quem está sem tempo porque está aprendendo C# 3, C# 4, VB 9, VB X, Oslo, EF, XAML, etc, etc, etc.)


Postado na(s) categoria(s) Azure pelo giovanni bassi em 17 de fevereiro de 2009 às 12:27 | Tags:

Promoting Azure Application from staging to production

Viram o botãozinho de "promote" de homologação para produção. Não preciso dizer mais nada, não é? Quero Azure! Now!


Postado na(s) categoria(s) Azure pelo giovanni bassi em 15 de fevereiro de 2009 às 00:48 | Tags:

Descobri ontem que nem tudo que funciona no Azure de verdade funciona durante o desenvolvimento com o Development Fabric e Development Storage, ao menos não durante o CTP atual. No caso, o que eu estava testando é a criação de tabelas dinamicamente, através de código. Não funciona. Além disso, várias outras não funcionam também, segundo o MSDN.

Se você se aventurar a criar uma tabela dinamicamente receberá o belo erro:

"Creating a new table dynamically is not supported in development storage"

Então, para quem quiser por algum código para testar com o Azure Table Storage, só resta o Azure de verdade? Não, há uma ferramenta feita para a criação da tabela do table storage, chamada DevTableGen. Você chama ela com os parâmetros corretos e tudo funciona (notem o "Windows Azure SDK Environment – tem até prompt de comando para Azure):

DevTableGen criando uma tabela no banco de dados

Só que eu penei até descobrir. Há restrições nas entidades, você é obrigado a criar uma entidade que tenha as propriedades "PartitionKey" e "RowKey", não pode dar a elas o nome que quiser.

Espero que resolvam isso logo… O código que eu estava usando antes para criar a tabela dinamicamente era bem mais simples do que ter ficar usando ferramenta de linha de comando. Vejam a classe de contexto:

    public class AzureContext : TableStorageDataServiceContext
    {
        public TableStorage TableStorage
        {
            get
            {
                var account = StorageAccountInfo.GetDefaultTableStorageAccountFromConfiguration();
                var ts = TableStorage.Create(account);
                return ts;
            }
        }        
        public IQueryable<Models.Message> Messages
        {
            get
            {
                return this.CreateQuery<Models.Message>("Message");
            }
        }
    }

Depois chamava simplesmente a propriedade TableStorage e criava a tabela. Vejam a ação (com ASP.Net MVC):

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult CreateTables(string tableName)
        {
            var ctx = new MvcApplication1.AzureContact.AzureContext();
            var tableCreated = ctx.TableStorage.TryCreateTable(tableName);
            if (tableCreated)
                TempData.Add("tablescreated", "Tables created sucessfully");
            else
                TempData.Add("tablescreated", "Tables already existed");
            return RedirectToAction("CreateTables");
        }

Simples, certo? Mas não funciona na nuvem, durante o deseenvolvimento você recebe uma bela exceção de presente. Na nuvem eu testei, funciona.

Vocês viram a propriedade "Messages", que retorna um "IQueryable<Message>"? Pois é, o DevTableGen usa esta informação para criar a tabela, ele reflete o assembly, procura por classes que herdam de DataServiceContext (como "TableStorageDataServiceContext", da qual meu "AzureContext" herda), e nestas classes procurar por "IQueryable"s que tenham tipos com os atributos corretos ("DataServiceKey") e as duas propriedades obrigatórias. Se você não fizer tudo direitinho recebe uma bela mensagem de erro do DevTableGen:

DevTableGen : error DG10 : No tables were generated. Either no candidate classes were found or they did not meet the requirements for the table storage.

Vejam a entidade:

    [DataServiceKey("PartitionKey", "RowKey")]
    public class Message
    {
        //sender
        public string PartitionKey { get; set; }
        //date sent
        public string RowKey { get; set; }

        public string Body { get; set; }

        public string Subject { get; set; }

        public int Length { get; set; }

        public Message()
        {
        }

        public Message(string sender, string body)
        {
            this.PartitionKey = sender;
            this.Body = body;
            this.RowKey = DateTime.UtcNow.ToShortDateString();
            this.Length = body.Length;
        }
    }

Outra coisa engraçada é que o Development Storage (DS) não é assim tãããããããão avançado quanto eu pensava. O que ele faz é criar uma tabela de verdade no banco de dados, igualzinho o esquema da classe. Dêem uma olhada:

image

É claro que a implementação em produção, na nuvem, não é assim. Lá você pode usar uma "tabela" virtual para guardar objetos de tipos diferentes, o que seria incompatível com esse tipo de design. Imagino que também não deve ser possível trocar o esquema da entidade e continuar usando o development storage, provavelmente você teria que recriá-lo (com o DevTableGen).

Quando anunciaram que o DS era a nuvem na sua casa eu pensei "uau, os caras fizeram algo poderoso só para eu poder simular o que acontece de verdade". Não é bem, assim, não é?

Bom, estamos em CTP, certo? Não dá para exigir tanto, mas eles bem que podiam avisar que era "quase" igual, para não criar uma expectativa que depois não é atendida. Vamos aguardar o próximo CTP para ver se isso é resolvido. Na prática, o impacto durante o desenvolvimento é mínimo.


Postado na(s) categoria(s) Azure pelo giovanni bassi em 30 de janeiro de 2009 às 00:06 | Tags:

No Windows Azure existe uma tecnologia para armazenamento de dados estruturados chamada Table Services. Ainda estamos em CTP, então pode ser que tudo mude, mas já há uma gama razoável de tipos, e nos meus testes tudo funcionou bem. E tudo é feito baseado em Astoria (ADO.Net Data Services), o que facilita muito. O único problema que tive é que algumas funcionalidades que existem no Azure não estão disponíveis no development fabric/development storage, que é onde desenvolvemos localmente.

Ao utilizar o Table Services o Azure funciona apenas como um hospedeiro de dados na nuvem. A aplicação pode estar rodando em qualquer lugar que tenha acesso a chamadas HTTP (lembre que tudo vai via REST). Pode rodar inclusive no próprio Azure Hosting.

Estou trabalhando e estendendo umas demos disponibilizadas no PDC (você pode ver alguns vídeos aqui e aqui), e por isso os meus exemplos deste post vão seguir o código realizado no PDC. Infelizmente eles não liberaram o código, então vou eu mesmo colocar o código que fiz, e que está funcionando, aqui para vocês baixarem.

Antes de mais nada uma observação: Essa não é uma aplicação baseada em boas práticas de programação ou arquitetura, é só um teste da tecnologia. Há varios problemas sérios que teriam que ser refatorados para que a aplicação ficasse com um mínimo de decência com relação a boas práticas.

O projeto é feito com ASP.Net MVC, do zero, sem utilizar os templates do Visual Studio para cloud apps. Você cria uma aplicação ASP.Net MVC (fiz a minha já com o código do Release Candidate), faz umas referências a um código do Samples do CTP, outra para uma dll do Astoria, e já está habilitado para criar aplicações com Table Services do Azure.

O projeto tem duas entidades: canais (channels) e mensagens (messages). Elas são representadas por classes POCOs, não fosse por um atributo no nível da classe. É tudo que você precisa fazer para que a classe vá parar no Azure Table Storage.

Essa é a entidade de canais. Ela tem apenas 3 propriedades: PartitionKey, RowKey e DateCreated.

    [DataServiceKey("PartitionKey", "RowKey")]
    public class Channel
    {
        public string PartitionKey { get; set; }
        public string RowKey { get; set; }

        public DateTime DateCreated { get; set; }

        public Channel()
        {
        }

        public Channel(string name)
        {
            this.DateCreated = DateTime.UtcNow;
            this.PartitionKey = name;
            this.RowKey = string.Empty;
        }
    }

Essa é a entidade de Mensagens. Ela tem um método, chamado MakeKey que auxilia a cria a chave de partição (PartitionKey). Fora isso tem apenas 7 propriedades, sendo duas as obrigatórias PartitionKey e RowKey, e mais 5 bem simples:

    [DataServiceKey("PartitionKey", "RowKey")]
    public class Message
    {
        //channel name
        public string PartitionKey { get; set; }
        //datetime of creation
        public string RowKey { get; set; }

        public string Text { get; set; }
        public string Author { get; set; }
        public string Channel { get; set; }
        public DateTime DatePosted { get; set; }
        public int Rating { get; set; }

        public Message()
        {
        }

        public Message(string channel, string author, string text)
        {
            this.Text = text;
            this.Author = author;
            this.Channel = channel;
            this.DatePosted = DateTime.UtcNow;
            this.PartitionKey = MakeKey(channel, this.DatePosted);
            this.RowKey = System.Xml.XmlConvert.ToString(this.DatePosted,
                System.Xml.XmlDateTimeSerializationMode.Utc);            
        }

        public static string MakeKey(string channel, DateTime dt)
        {
            return channel + "@" + dt.ToString("yyyy-MM-dd");
        }
    }

Temos ainda uma classe chamada MicroData que é a responsável pelo contato com o Azure, e é um herdeiro do contexto do Astoria. Essa classe "TableStorageDataServiceContext" herda da classe "DataServiceContext" do Astoria. É a típica classe que ficaria escondida no repositório da aplicação.

    public class MicroData : TableStorageDataServiceContext
    {
        public IQueryable<Channel> Channels
        {
            get
            {
                return this.CreateQuery<Channel>("Channels");
            }
        }
        public IQueryable<Message> Messages
        {
            get
            {
                return this.CreateQuery<Message>("Messages");
            }
        }
    }

Com isso todo o contato com o Azure já pode ser feito. As iterações são feitas através do contexto (a classe MicroData). Tudo bem simples, você usa as propriedades que criou na classe MicroData para acessar as respectivas tabelas (propriedades "Channels" e "Messages"). Há também um código para criar as tabelas, mas não vou mostrar para não desviar do assunto. Pense que cada entidade tem uma tabela lá no Table Services.

Por exemplo, para recuperar canais:

            var svc = new Models.MicroData();
            ViewData["channels"] = svc.Channels;

Ou então com LINQ, recuperando mensagens:

var q = from m in svc.Messages 
        where m.Author == name 
        select m; 

ViewData["msg"] = q;

Para inserir dados também é bem simples. Abaixo o código para inserir uma mensagem.

            var svc = new Models.MicroData();
            var m = new Models.Message(channel, author, msg);
            svc.AddObject("Messages", m);
            svc.SaveChanges(); 

Se você já viu uma demo de Astoria, vai ver que não muda praticamente nada.

Você pode pegar o código completo dos meus testes aqui. Se você tem o ASP.Net MVC ele vai abrir normalmente, se você não tem… eu te pergunto: porque você ainda não tem?

Depois eu comento os detalhes da criação da infra para usar o com Azure assim como outros detalhes conceituais.


Postado na(s) categoria(s) Azure pelo giovanni bassi em 29 de janeiro de 2009 às 02:01 | Tags:

Continuo estudando o Azure. Dessa vez estou dando uma boa olhada no Table Storage.

Eu já tinha visto a demo, mas não tinha digerido direito. Agora entendi. E vou contar uma coisa para vocês: como é tudo baseado em REST, e o Astoria (atual ADO.Net Data Services – dá-lhe codinomes) integra perfeitamente.

Perfeitamente até demais.

Ok, REST é algo grande, importante, e independente da existência do Azure. Mas realmente parece que o Astoria foi criado somente para auxiliar na integração com o Azure. Sem ele a Microsoft teria que confiar em algo proprietário, e aí metade do mundo xiita ia reclamar. Com ele tudo ficou simples e fácil. E realmente é fácil (apesar de poder melhorar bastante). Todo o acesso é feito baseado em LINQ para ADO.Net Data Services.

O casamento das tecnologias é realmente muito bem feito. Em seguida vou postar um exemplo.


Postado na(s) categoria(s) Azure pelo giovanni bassi em 29 de janeiro de 2009 às 01:49 | Tags: ,

Acabo de colocar na nuvem meu primeiro projeto com Windows Azure. Fiz um simples validador de CNPJ, por não precisar chamar banco de dados nenhum.

Vocês podem acessá-lo aqui:
http://helloclearskies.cloudapp.net/
(Fiz uma brincadeira na URL. Vi o Waldemir Cambiucci chamando o dele de "Hello Cloud" e como só chove em São Paulo, nada como um "Hello Clear Skies" para variar, não é?)
Vejam aqui imagem dele rodando:

Aplicação rodando hospedada no Windows Azure

Enfim, é um validador de CNPJ, e ele está lá no datacenter da Microsoft, funcionando perfeitamente.

Mais comentários a se somar aos últimos que eu já havia feito:

  1. O suporte ao Ajax funciona, vocês podem ver dois UpdatePanels rodando nesta aplicação, fazendo callbacks normalmente;
  2. Os validadores funcionaram também (esse era até esperado, certo?);
  3. O deploy é demorado, alguns minutinhos, que parecem mais do que são de verdade, porque você está ansioso para ver o resultado;
  4. A aplicação sobe e não inicia. Você precisa clicar no "start". E demora para iniciar. Mais ansiedade.
  5. Após iniciada a primeira chamada demora um pouco, natural, é .Net, está JITing. Depois vai bem rápido.
  6. O deploy de staging para production é muito rápido. Um simples clique e poucos segundos. E já sobe rodando.
  7. Todo o processo de desenvolvimento é muito rápido. Até aqui, com uma aplicação sem acesso a dados, não é absolutamente nada diferente de uma aplicação comum.
  8. O Azure derrubou o Visual Studio 2008 duas vezes durante o desenvolvimento. É o segundo CTP público, então tudo bem. Só achei que, para uma aplicação tão simples não era para tanto. Nada de mais, no entanto.

A interface gráfica de administração eu já havia visto no S+S Day, e ficou muito bonita. Agora… porque eles não fizeram em Silverlight? Será que vai migrado até a versão final?

Vejam a interface de admininstração:

Administração do projeto no Windows Azure

E vocês, já fizeram seu primeiro? Como foi?


Postado na(s) categoria(s) Azure pelo giovanni bassi em 19 de janeiro de 2009 às 01:47 | Tags:

Quem é Giovanni Bassi

Giovanni Bassi Sou uma pessoa apaixonada por tecnologia e especificamente por .Net. Sou consultor independente especialista em .Net, focado em arquitetura e melhores práticas. Tenho dezenas de artigos publicados na .Net Magazine, revista da qual sou editor técnico. Ministro palestras e cursos de vez em quando, e quando dá tempo eu respiro um pouco. Mais detalhes nesta página.

Busca

Selos

Eu vou ao TechEd Brasil 2010, e você?

MVP

MCPD

MCSD

.Net Magazine

Abaixo ao if!

Calendário

«  setembro 2010  »
seteququsedo
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910
Ver detalhamento de posts no calendário

Blogs interessantes

    OPMLDownload OPML file

    Postagens recentes

    Comentários recentes

    Disclaimer / Aviso
    As opiniões colocadas neste blog são minhas e pessoais e não expressam necessariamente as opiniões de meus empregadores, pareceiros e amigos. Da mesma forma, os comentários feitos por leitores do blog não expressam a minha opinião.

    © Copyright 2010 .Net Unplugged
    Log in