Archive for the ‘Architectures’ Category

Publishing RTSP Streams on FMS! How?

For those who have ever used the Flash Media Server for video streaming, the idea of publishing a stream encapsulated in RTSP (Real Time Streaming Protocol) may seem quite strange, maybe even impossible. This is because the basic (and only) protocol used for FMS client-server communication is the RTMP (and its variations), a proprietary protocol for media streaming, from Adobe. However, in some circumstances the use of an RTMP input is almost impossible, especially when this input stream comes from legacy systems, or from external services. These specific cases require an approach where the content from a RTSP source is delivered using RTMP, that is, a translation from RTSP to RTMP via content repackaging.

The easiest way to perform this translation is using Wowza Media Server, an alternative to FMS that has many interesting features, including the RTSP input support. The problem is that sometimes is impossible to change the video architecture from FMS to other solution, especially when we have developed several applications, or when the whole environment is integrated, up, and running.

In this situation, the intuitive solution would be: we can setup a layer of Wowza Media Server before FMS Servers, working like a translation layer. With this layer, the FMS would receive a RTMP stream exactly like it receives from Flash Media Encoder, making the translation fully transparent. The challenge of this solution is that the Wowza Server cannot publish streams on FMS, so, it cannot act like a FME (from FMS perspective).

To deal with this limitation, we need to change the stream flow paradigm from push to pull, or, in other words, we need to force FMS to get the stream from Wowza. With this architecture configuration, the FMS is no longer a passive component. It is its responsibility to, not only get the video stream, but to perform the failover of the input streams, which can be done through stream multiplexing.

This change in FMS role is only possible if we use server side action script, to connect to Wowza, and to pull the stream flow. Basically, we use NetConnection and Stream classes, to establish a remote connection and to play some content (Wowza stream) through it:

myRemoteConn = new NetConnection();
myRemoteConn.connect("rtmp://wowzaserverhost/streamtest");
myStream = Stream.get("myStream");
myStream.play("my_stream.sdp", 0, -1, true, myRemoteConn);

As we can see, we can use the FMS to delivery RTSP streams without great architecture changes. With Wowza Media Servers and some server side AS, it’s not too hard to make the impossible, possible!

Advertisements

Stream Multiplexing for FME Failover in Flash Media Server

As some may wonder, I decided write my posts in English from now, so, anyone can follow the ideas that are discussed here. To start this new era, I decided to talk a bit about how we can do the failover of live streams in Flash Media Server through internal multiplexing of signals, that is, how we can use a single live stream as a backup of several others, without burdening bandwidth available between the Flash Media Encoder and the Flash Media Server.

To get the goal of this idea a little clearer, let’s suppose that we want to perform a live transmission, where we have 3 servers running an instance of Flash Media Encoder each, and we have 3 different signals (eg cameras), linked to a each encoder. If one of these servers crashes, the stream will no longer be published on Flash Media Server, and inevitably users connected to this content will have their experience interrupted. In order to avoid this problem, we can detect that a stream is no longer running, and then send to users the signal of another encoder, in a transparent way, without playback interruption (lost of connection or rebuffering). This approach dispenses the use of a backup server for each active server, which significantly reduces the investment in hardware and bandwidth, in environments with high availability needs.

The main concept behind this approach is the separation between the publishing streams and the viewing streams, which means that the users should not connect directly into the stream published for Flash Media Encoder. In fact, users should connect to a fake stream, and the published content will be dynamically linked to it via a server side Action Script. This idea is very well explained in the article “Building a Live Video Switcher with Flash Communication Server MX“, which was the base of multiplexing for failover concept. To automate this association between publisher stream and viewers, we can use the application.onPublish and application.onUnpublish events, which are triggered when a signal is, or ceases to be published in Flash Media Server.

The challenge now is how to control, automatically, which is the backup stream and which is the main, that is, not simply store a list of active streams, we need to know which stream will be displayed to users if a failure occurs in main stream. One approach is to isolate each stream in a different instance of application, and, in addition, create two different types of applications, one for the main streams (master) and one for the backups. Each master instance will have only one stream available so that users can connect, which means that we will need to have as many instances as the number of live signals.

The main application should store/remove from a list all the active/inactive live streams (via events), so that the first stream of the list always will be associated with the stream being viewed by users. If this stream is unpublished, the application should join the users stream to the next item, which means that the backup will always be the next stream on the list.

The backup application should receive a live signal and publish it in the main applications, performing an internal multiplexing. These internal streams will be stored on main instances as backups, so, all main applications will have the same backup streams. This internal multiplexing can be implemented in a very simple way using the NetConnection and NetStream classes, also available for server side scripting.

To make clear the idea presented above, let’s take a look at this picture:

Failover for FME Streams

Failover for FME Streams

As we can see, this approach is a simple and efficient way to implement the failover of streams published by FME, which is very important in environments where high availability is a imperative requirement, and where the investment resources for bandwidth and hardware are limited.

More information about Flash Media Server Development can be found in Adobe Developer Connection

Otimizando um Servidor Web para Download Progressivo

No dia 27 do mês passado estive no Congresso SET, da Sociedade Brasileira de Engenharia de Televisão e Telecomunicações, onde apresentei junto com o Marcello Azambuja um artigo sobre Arquiteturas de Distribuição de Vídeos na Internet. Porém, devido ao tempo bastante limitado da apresentação, não pude entrar em detalhes mais específicos de como otimizar as arquiteturas para obter um melhor desempenho. Por isso, resolvi colocar um pouco do que está no artigo aqui no blog, já que nem todo mundo que tem interesse neste assunto estava na apresentação. (O slides podem ser vistos aqui)

Assim, resolvi começar falando especificamente sobre o Download Progressivo, ou seja, como podemos otimizar um Web Server para que ele seja capaz de servir a maior quantidade de usuários possível. No caso de distribuição de vídeos via Progressive Download temos algumas características básicas que devem ser consideradas para otimização:

  • As conexões com o WebServer são persistentes, ou seja, o usuário fica conectado ao servidor por uma quantidade razoável de tempo, até que o conteúdo seja completamente copiado;
  • Dependendo da quantidade de vídeos diferentes podemos ter diversos conteúdos diferentes sendo acessados simultaneamente;
  • Os arquivos de mídia não estão necessariamente nos discos do servidor. Eles podem estar em um repositório central sendo acessados pelo servidor Web através de NFS/CIFS;
  • A quantidade de acessos ao serviço pode aumentar rapidamente, variando de acordo com o conteúdo disponibilizado;

Com estas características já podemos identificar alguns gargalos principais:

  • Tráfego de rede: muitos usuários conectados realizando download irão rapidamente ocupar a banda disponível. Além disso, existe a ocupação de banda pela cópia dos arquivos do repositório central para o servidor;
  • IO (Repositório Central e Disco Local): muitos usuários realizando download significa muito IO de leitura, que é maior a medida que temos mais usuários acessando arquivos diferentes;
  • Memória: quanto mais usuários, mais memória o Apache irá precisar para atendê-los, e quanto mais arquivos, mais memória o kernel irá utilizar para cache;
  • CPU: quanto mais usuários mais processamento para organizar e servir as requisições;

Na verdade, se queremos obter o máximo de uma arquitetura não podemos nos limitar a olhar apenas um componente. O primeiro ponto, e mais simples, consiste em alterar as configurações do Apache, escolher a versão correta (2.X), e compilar uma versão do Web Server que tenha apenas aquilo que é relevante para a distribuição de arquivos, ou seja, devemos evitar incluir na configuração de compilação módulos que não serão utilizados, como mod ssl, por exemplo.

Uma vez compilado cabe a nós decidir qual arquitetura interna de funcionamento possui uma performance maior: se é a multi-process (Apache Prefork) ou a multi-process/multi-thread (Apache Worker).

Basicamente, no prefork, para cada conexão será criado um processo específico para atendê-la, de modo que a quantidade de processos httpd será sempre maior ou igual a quantidade de clientes. Nesta arquitetura, temos uma quantidade inicial que processos que são pré-criados para atender as conexões, sendo que a medida que os clientes se conectam, eles são atendidos por estes processos. No prefork, temos basicamente dois problemas em termos de performance:

  • Memória: cada processo criado ocupa uma porção da memória, de modo que a memória disponível para cache do kernel é cada vez menor, ao ponto que toda ela é preenchida pelos processos httpd, momento onde o servidor começa a fazer swap em disco;
  • Load: a criação de novos processos (fork) gera um overhead no sistema, de modo que quanto maior a taxa de conexão, maior será o overhead no fork para atender as novas conexões;

A outra opção de MPM, o worker, trabalha com o conceito multi-thread, onde as requisições são atendidas por threads e não por processos. Assim, teríamos apenas um ou poucos processos com múltiplas threads em cada um deles, atendendo cada uma das conexões. Com o worker, minimizamos a utlização de memória, já que as threads compartilham a mesma área de memória do processo pai, e reduzimos o overhead na criação de processos. Na verdade, no caso do worker, definimos a quantidade de threads por processo de modo que só realizamos um fork quando este limite é atingido.

A escolha entre prefork ou worker deve ser realizada caso a caso, ou seja, dependendo da situação de uso e da configuração de hardware uma escolha poderá ser melhor que a outra. No caso específico de servidores para utilização em distribuição de vídeos em Progressive Download, a escolha do MPM Worker é recomendada, com o objetivo de reduzir a ocupação de memória pelo servidor Web, deixando-a livre para que o kernel possa utilizá-la para cache de conteúdo, reduzindo o IO no disco e conseqüentemente o tempo de resposta da requisição. Uma configuração interessante seria neste caso seria forçar a criação de todos os processos filho (children) e suas threads no momento que o servidor Web for iniciado, reduzindo assim o overhead de controle de threads.

Além de configurar o MPM, o Apache permite diversas outras configurações capazes de aumentar o desempenho do mesmo, como a possibilidade de desabilitar Hostname Lookups e DNS resolving, e outras que podem ser encontradas na documentação do Apache.

Entretanto, quando falamos de arquiteturas de distribuição de vídeo que recebem grandes volumes de acesso, devemos nos preocupar um pouco mais em como otimizar o processo de distribuição. Uma das maneiras mais eficientes de aumentar a capacidade de uma infra-estrutura de Download Progressivo consiste em realizar um processo de cache intensivo. Ter uma estratégia de cache de conteúdo é fundamental quando falamos de alta performance com um grande volume de acessos. Quando temos um volume muito grande, temos também diversos requests ao mesmo conteúdo. Processar todo o request para cada cliente consistiria em repetir as mesmas operações diversas vezes, sem aproveitar para um request os dados processados por outro. Assim, fica claro que podemos otimizar este processamento, simplesmente aproveitando aquilo que serve para mais de uma requisição.

Em situações onde temos uma arquitetura onde o Apache funciona como uma espécie de “proxy” entre o usuário e um repositório central de vídeos, essa necessidade é ainda mais latente, uma vez que não faz sentido obter um mesmo arquivo diversas vezes neste repositório para servir para os clientes a cada request semelhante. Uma vez copiado do storage para o Apache, para servir uma requisição, o arquivo pode ser mantido no servidor Web para as requisições posteriores realizadas ao mesmo vídeo. Com essa abordagem, reduzimos a carga no storage e o tráfego de rede e de operações de cópia.

Para realizar o cache de conteúdo existem diversas alternativas, como o Squid e o mod_cache. O mod_cache, por estar integrado ao Apache e por ser bastante conhecido e utilizado, além de apresentar uma ótima performance, é uma excelente opção para cache em arquiteturas de distribuição em Download Progressivo.

O mod_cache permite duas abordagens principais de cache: disco ou memória. O mod_disk_cache é o módulo responsável pelo cache em disco, e funciona da seguinte forma: ao receber um request, o mod_disk_cache verifica se o conteúdo solicitado já está no cache em disco. Se estiver, o módulo valida se o conteúdo não está expirado e serve o mesmo a partir do cache, sem que a requisição seja passada aos demais módulos do Apache. Caso, não esteja cacheado, o request passa pelo path normal de atendimento ao request, sendo que, ao finalizar o processamento, o mod_cache escreve a resposta no cache antes de servir a mesma. Assim, ele cria dois arquivos em disco: o .data, com o conteúdo do request, e o .header com os headers da resposta. O nome dos arquivos criados é criado a partir de um hash, para evitar que o conteúdo seja sobre-escrito.

O mod_mem_cache, é o módulo responsável pelo cache em memória, e funciona de forma semelhante ao mod_disk_cache, porém armazenando o conteúdo em memória.

A escolha de um dos módulos para utilização em um servidor de Download Progressivo também depende da configuração do hardware. Entretanto, em servidores que rodam em Linux, o uso do mod_disk_cache é recomendada, uma vez que o gerenciamento do cache em memória feito pelo kernel é bastante eficiente.

Com um web server bem otimizado e configurado, e com uma estratégia de cache eficiente, temos uma arquitetura de distribuição muito mais robusta e capaz de atender um volume até 70% maior que o volume que atenderíamos utilizando apenas um servidor com as configurações “default”, o que reduz de forma significativa os custos de investimento para expansão da capacidade, tornando esta uma opção bastante interessante para distribuição de vídeos na internet.

Escolhendo a melhor arquitetura para delivery de vídeos

Apesar de parecer algo simples, a escolha correta de uma arquitetura de delivery de mídia é tão fundamental para o serviço quanto a definição dos parâmetros de codificação, isto porque ela também pode impactar de forma decisiva na qualidade da experiência do usuário. Distribuir um vídeo que demora muito para carregar, ou que “trava” constantemente, muitas vezes é pior do que ter uma experiência contínua porém com pior qualidade. Por isso, a escolha da arquitetura de delivery está fortemente atrelada ao target bitrate escolhido.

Existem duas formas básicas de se distribuir vídeos na internet: via Streaming ou Progressive Download. O streaming é a tecnologia que permite o envio de informação através de pacotes, que são solicitados sob demanda pelo cliente, ou seja, o cliente solicita ao servidor apenas os pacotes necessários para exibir o conteúdo em um determinado momento. Uma vez consumidos, os pacotes deixam de existir na máquina do cliente. O progressive download, nada mais é que um simples download, porém com a vantagem de que o usuário pode começar a reproduzir o conteúdo sem que seja necessário que o download esteja finalizado. No progressive download, o conteúdo é efetivamente copiado para a máquina do usuário, e, de acordo com as diretivas de cache, pode ficar armazenado lá por um determinado período de tempo.

Vocês agora podem se perguntar qual dessas duas opções é melhor, e a resposta é simples: depende dos seus objetivos e das características do cenário em que a solução será utilizada. Simplificando, você deve se fazer as seguintes perguntas antes de escolher qual modelo de distribuição será utilizado:

  • Qual o target bitrate total dos vídeos que serão distribuídos?
  • Qual é a largura de banda disponível média dos usuários que irão acessar o conteúdo?
  • A segurança do conteúdo é uma prioridade? (Pirataria)
  • Os custos da infra-estrutura são um fator limitante?

Se suas respostas indicam que a largura de banda disponível média dos usuários é pelo menos 20% maior que o target bitrate total dos vídeos que serão distribuídos, então a situação é bastante confortável, e a escolha entre streaming e progressive download será decidida nas outras duas questões. Caso a segurança seja uma preocupação primordial, ou seja, o conteúdo oferecido é altamente sensível à pirataria, então recomendo fortemente a utilização do streaming. Isto porque o conteúdo distribuído via streaming não fica armazenado no cliente após a reprodução, o que dificulta um pouco as coisas para o lado de quem quer copiar. Além disso, não é possível fazer o download do arquivo através de um simples GET HTTP, já que a maioria dos servidores de streaming utilizam protocolos diferentes (rtmp para Flash e rtsp para WMV). Entretanto, não pense que será impossível copiar o conteúdo, já que existem alguns programas que “tocam” o vídeo como se fossem um player, mas na verdade estão copiando o bitstream para um arquivo local (WMRecoder, etc).

Por outro lado, ainda no cenário ideal onde a disponibilidade de banda é maior que o target bitrate, caso os custos sejam uma preocupação crítica, então a melhor opção seria o progressive download, já que podemos montar um servidor utilizando apenas tecnologias open-source (Apache), e podemos compartilhar os recursos com outras aplicações, como um web-server. Desta forma, não é necessário um hardware dedicado ao serviço, o que pode acontecer utilizando streaming, principalmente em Windows Media. Além disso, um servidor de progressive download suporta, naturalmente, mais conexões que um servidor de streaming, já que ele dispensa uma série de controles do fluxo de bits de cada conexão.

Voltando ao mundo real, o que acontece quando a disponibilidade de banda dos usuários não é lá grandes coisas? Neste caso, a melhor opção é sem dúvidas o progressive download. Caso o usuário não tenha uma banda disponível suficiente e a distribuição seja feita via streaming, a reprodução do conteúdo será interrompida constantemente para rebufferings, já que o fluxo de bits de saída é maior que o de entrada, e não há nada mais irritante para o usuário do que interrupções na reprodução. O mesmo problema acontece para o progressive download, com um porém: o YouTube ensinou uma valiosa lição para o usuário, “aperte o pause e espere carregar”! Assim, a diferença, neste caso, entre o streaming e o progressive download, está na possibilidade de pausar a reprodução até que o conteúdo esteja suficientemente carregado para uma reprodução contínua. Esta é uma “feature” que definitivamente faz toda diferença quando falamos na satisfação do usuário.

Um bom argumento daqueles que defendem o uso do streaming é a possibilidade de seek para qualquer posição do vídeo, independente da necessidade de carregamento. Entretanto, se estivermos falando de Flash Vídeo, este argumento é totalmente inválido. Com Flash Vídeo podemos implementar de forma relativamente simples uma solução de seek para qualquer posição, sem que seja necessário que a posição desejada já tenha sido recebida (mod_flv_streaming).

Resumindo, a escolha entre progressive download e streaming deve ser feita baseada nas características específicas de cada situação, e não podemos dizer para usar sempre um ou outro, pois ambos possuem vantagens e desvantagens. Na verdade, a chave para escolha da melhor arquitetura consiste na avaliação correta de todos os pontos envolvidos no processo de delivery, considerando assim os trade-offs de cada solução.

Otimizando a performance com diferentes estratégias de cache

De todas as maneiras existentes de se otimizar a performance de um software, acredito que a utilização de um cache intensivo é aquela que produz os melhores resultados, principalmente quando falamos de aplicações web. A utilização de uma estrutura de cache eficiente, aumenta significativamente a capacidade de processamento de requisições, uma vez que reduzimos a pressão sobre os gargalos da aplicação, sejam eles relacionados ao IO em disco, a utilização de memória ou a utilização de CPU. Para cada tipo de gargalo, e para cada tipo de aplicação, podemos utilizar uma estratégia de cache diferente, atuando diretamente nos pontos que limitam o desempenho do sistema.

Em uma aplicação web, temos três tipos básicos de cache: o cache no cliente, o cache no web server e o cache na aplicação. O cache no cliente é o método mais simples de redução de carga nos servidores web, principalmente quando falamos de sites simples, e com grande quantidade de conteúdo estático. Imagine, por exemplo, um site que possui muitas imagens e textos estáticos. Se não utilizarmos nenhuma política de cache, a cada request realizado, todos os componentes serão enviados do servidor para o cliente, mesmo que este cliente já tenha visualizado a página diversas vezes. Todas as imagens que já foram transferidas para ele, e que não sofreram alteração, serão novamente enviadas, algo que poderia ser facilmente evitado se o cliente tivesse armazenado previamente este conteúdo estático. Para que o cliente armazene este conteúdo, o servidor deve mandar, juntamente com a resposta, a informação de que aquele conteúdo deve ser cacheado, e por quanto tempo ele será válido no cache. Para isto, existem dois módulos do Apache que permitem uma excelente flexibilidade na definição de qual conteúdo será cacheado e o tempo de expiração do mesmo. São eles: mod_headers e mod_expires.

ExpiresByType text/html “access plus 2 hours”
ExpiresByType image/gif “modification plus 3 minutes”

Algumas vezes, apesar de termos conteúdo estático, a utilização de cache no cliente não faz muito sentido. Imaginem um site de download de músicas, onde temos diversos servidores web servindo conteúdo estático a partir de um repositório central de arquivos (um storage comum). Se vários usuários diferentes tentam realizar o download de um determinado arquivo, a cada requisição o web server irá ler o mesmo arquivo do storage central, gerando uma carga desnecessária no backend. O mesmo pode ser aplicado se no backend temos um servidor de aplicação, onde o conteúdo gerado se altera com pouca freqüência ou com uma periodicidade definida. Neste caso, devemos utilizar uma estratégia de cache no web server, seja no próprio servidor, seja criando uma camada de cache entre ele e o usuário.

Existem diversos modos de se implementar um cache no servidor web, seja utilizando um Squid na frente, seja utilizando um appliance dedicado. Porém, a maneira que eu acho mais eficiente é utilizando o mod_cache. O mod_cache é um módulo do Apache específico para cache no web server, capaz de armazenar conteúdo em disco ou em memória, de acordo com as necessidades da aplicação. Por estar integrado ao Apache, sua configuração é extremamente simples e não existem problemas de compatibilidade, etc. Além disso, ele é bastante confiável (quando utilizado com o Apache 2.2.x) e é Open-Source, sendo suportado por uma comunidade bastante ativa. (para quem quiser saber mais sobre o mod_cache).

Em algumas situações específicas estas duas abordagens de cache não são suficientes, sendo necessário a utilização de uma terceira: o cache da aplicação. Existem casos onde a camada de aplicação necessita de consultar serviços remotos, ou mesmo bancos de dados, para gerar uma determinada saída. Nestes casos, seria razoável que fosse armazenada a resposta de uma determinada consulta, desde que ela possa ser reaproveitada para o processamento de outras requisições. Desta forma, aumentamos a velocidade de resposta, o que bastante interessante do ponto de vista do usuário. Assim, para realizar este tipo de cache, podemos, por exemplo, utilizar o memcached, que é uma excelente ferramenta de cache de dados em memória.

Em suma, temos diferentes tipos de cache para diferentes tipo de problemas, sendo que a utilização de uma política de cache correta garante um ganho substancial de desempenho (podemos ter ganhos de até 70%). Quanto mais intensiva e bem estruturada for a utilização de cache, melhor será a utilização dos recursos para o que realmente importa e menor será o tempo de resposta para o usuário.

Scaling Down

Quando falamos de arquiteturas escaláveis, a primeira coisa que nos vem a mente é ter um projeto de hardware/software que permita o aumento da capacidade de processamento de acordo com o aumento da demanda. Isto significa que o esforço para atender uma demanda crescente deve ser o mínimo possível, limitando-se, na maioria das vezes, apenas em investimento em infra-estrutura de hardware. Entretanto, o conceito de escalabilidade é muito mais amplo que isto, e não deve ser limitado às condições de crescimento da demanda, mas também deve considerar uma redução significativa desta. O problema é que a grande maioria das pessoas que projetam arquiteturas estão preocupadas apenas com o scaling up e se esquecem totalmente do scaling down, e isto pode ser bastante arriscado também. Theo Schlossnagle, no seu livro Scalable Internet Architectures, nos dá inúmeros exemplos de empresas que, por não possuirem uma arquitetura totalmente escalável, simplesmente faliram durante o estouro da bolha da Internet por não serem capazes de cortar seus custos operacionais.

O problema de scaling down geralmente é mais comum em empresas de médio e grande porte, uma vez que a demanda inicial já é bastante grande, o que exige uma arquitetura inicial mais robusta e complexa. Porém, todo software tem um ciclo de vida, e existe uma probabilidade grande de que após alguns anos a demanda torne-se cada vez menor. Neste ponto, quando a demanda atual passa a ser menor que a inicial, muitas vezes a estrutura torna-se super dimensionada, e os custos de operação não são mais justificáveis. Além disso, nem sempre é interessante, do ponto de vista de posicionamento de negócios, tirar o software do ar. É aí que a necessidade de reduzir a estrutura vira uma questão de sobrevivência (sendo um pouco radical).

Você pode estar se perguntando agora: Se eu tenho uma arquitetura que é facilmente “escalável para cima”, porque ela não seria “escalável para baixo”? Quais são as características necessárias para um scaling down? Na verdade, em qualquer arquitetura existe um limite de quão simples e barata ela pode ser. O princípio geral da escalabilidade nos diz que quanto melhor for o isolamento entre as diferentes camadas do software, mais fácil é expandir a capacidade dos gargalos existentes nele. Para um scale down eficiente, também é fundamental que os componentes que foram isolados sejam construídos de forma uniforme, e rodem em plataformas compatíveis, de modo que todos os componentes possam coexistir em um único ambiente, que, no caso mais extremo, seria uma máquina Google Like. Esta é a visão ideal de escalabilidade: ter um software (inclusive com suas dependências), que seja capaz de rodar em uma máquina de supermercado, e que também possa funcionar perfeitamente em 50 servidores Dual Quad Core em cluster, e que a quantidade de informação processada varie linearmente de acordo com o aumento da capacidade.

Para que isto seja viável, é fundamental considerar os requisitos mínimos de cada componente, avaliando a compatibilidade destes requisitos com os demais componentes. Por exemplo, se um determinado componente só roda em Solaris, e o outro só em Windows, a coexistência dos dois em um único hardware fica comprometida. Atualmente, ainda temos a saída da virtualização, mas pode ser que nem todos os componentes rodem sem problemas em ambientes virtualizados. Além disso, requisitos mínimos de memória, disco e processamento irão delimitar o quão simples poderá ser a estrutura.

Resumindo, temos todos que nos preocupar não somente com o que fazer quando as coisas estão se expandindo, mas também é muito importante ter um plano claro de o que pode ser feito para enxugar a estrutura, direcionando os recursos para pontos mais prioritários. Quando você estiver projetando uma arquitetura, lembre-se de que em algum momento o scaling down pode ser a única alternativa para manter um produto no ar.