Sunday, 8 October 2017

Gráfica Média Em Movimento


Estou tentando renderizar um gráfico de grafite que tenha o motionAverage da soma do hitcount de várias métricas diferentes. Este objetivo: eu esperaria que a movimentação desse alvo: também funcionaria bem: no entanto, eu recebo a imagem temida sem dados. A saída do formato JSON não fornece informações úteis neste caso, infelizmente, retornando simplesmente. Como posso calcular a média móvel da soma acima na Graphite Ive tentou o seguinte sem sorte também: Obrigado pela sua ajuda. Obtenho dados em grafite com uma granularidade de uma hora. Por exemplo Agora, a Id gosta de poder representar esta evolução na evolução do valor para cada dia da semana, de modo que o valor real exibido é a soma (ou média) dos valores para esse dia da semana em algumas semanas (vamos Diga 2 semanas, por exemplo). O meu gráfico seria assim se eu apenas olharmos a semana passada: por exemplo, para o ponto de sexta-feira, leva os valores de hoje (1112), o valor da última sexta-feira (3) e faz uma média de ambos (( 1112) 3) 2 Isso é possível, como resumir (your. metric. goes. here, 1week, sum) irá resumir os dados em intervalos de 1 semana, somando-os. Você também pode usar avg, max, min. No que diz respeito à semântica, os temporizadores geralmente precisam ser calculados em média e os contadores precisam ser resumidos quando resumidos. Exemplo: Se você medir contagens de laptops e tempos de volta quando você corre todos os dias e quer um resumo semanal, você mede o tempo de lapso de sete dias e atribui-lo a esse lapso de tempo semanal. Com lap-count. Faz mais sentido saber o total, então você o resume. Em uma nota diferente: TimeStack e timeShift são usados ​​nos casos em que você deseja comparar os dados dos últimos meses com esses meses na mesma linha de tempo. Além disso, você pode personalizar também os dados resumidos. O Grafite 1 executa duas tarefas muito simples: armazenar números que mudam ao longo do tempo e graficando-os. Houve muitos programas escritos ao longo dos anos para fazer essas mesmas tarefas. O que torna o Graphite exclusivo é que ele fornece essa funcionalidade como um serviço de rede que é fácil de usar e altamente escalável. O protocolo para alimentar dados em grafite é simples o suficiente para que você possa aprender a fazê-lo manualmente em alguns minutos (não que você realmente quisesse, mas é um teste decisivo para a simplicidade). Renderizar gráficos e recuperar pontos de dados são tão fáceis quanto buscar um URL. Isso torna muito natural a integração de grafite com outros softwares e permite aos usuários criar aplicativos poderosos em cima do Graphite. Um dos usos mais comuns do Graphite é a construção de painéis baseados na web para monitoramento e análise. Grafite nasceu em um ambiente de comércio eletrônico de alto volume e seu design reflete isso. A escalabilidade e o acesso em tempo real aos dados são objetivos fundamentais. Os componentes que permitem que Graphite atinjam esses objetivos incluem uma biblioteca de banco de dados especializado e seu formato de armazenamento, um mecanismo de cache para otimizar as operações de IO e um método simples e eficaz de agrupamento de servidores de grafite. Ao invés de simplesmente descrever como o Graphite funciona hoje, vou explicar como o Graphite foi inicialmente implementado (de forma bastante ingenua), quais problemas eu encontrei e como eu planejei soluções para eles. 7.1. A biblioteca de banco de dados: armazenar gravações de dados da série de tempo é inteiramente escrita em Python e consiste em três componentes principais: uma biblioteca de banco de dados chamada sussurro. Um daemon back-end chamado carbono. E um webapp front-end que processa gráficos e fornece uma UI básica. Enquanto o sussurro foi escrito especificamente para grafite, ele também pode ser usado de forma independente. É muito semelhante ao design para o banco de dados round-robin usado pelo RRDtool e apenas armazena dados numéricos da série temporal. Normalmente, pensamos em bancos de dados como processos de servidor que os aplicativos do cliente falam sobre sockets. No entanto, sussurro. Muito parecido com RRDtool, é uma biblioteca de banco de dados usada por aplicativos para manipular e recuperar dados armazenados em arquivos especialmente formatados. As operações de sussurro mais básicas são criadas para criar um novo arquivo de sussurro, atualizar para escrever novos pontos de dados em um arquivo e buscar para recuperar pontos de dados. Figura 7.1: Anatomia básica de um arquivo de sussurro Como mostrado na Figura 7.1. Os arquivos de sussurro consistem em uma seção de cabeçalho contendo vários metadados, seguido por uma ou mais seções de arquivo. Cada arquivo é uma seqüência de pontos de dados consecutivos que são pares (timestamp, value). Quando uma operação de atualização ou busca é realizada, o sussurro determina o deslocamento no arquivo onde os dados devem ser gravados ou lidos, com base no timestamp e na configuração do arquivo. 7.2. O fim de trás: Um serviço de armazenamento de serviços simples O fim de semana de grafites é um processo do daemon chamado carbono-cache. Geralmente simplesmente referido como carbono. É construído em Twisted, uma estrutura IO altamente orientada para eventos escalonada para Python. Twisted permite que o carbono converse eficientemente com um grande número de clientes e manipule uma grande quantidade de tráfego com baixa sobrecarga. A Figura 7.2 mostra o fluxo de dados entre o carbono. Sussurro e webapp: os aplicativos do cliente coletam dados e enviam-no para a parte traseira da grafite, carbono. Que armazena os dados usando sussurro. Estes dados podem então ser usados ​​pelo webapp grafite para gerar gráficos. Figura 7.2: Fluxo de dados A principal função do carbono é armazenar pontos de dados para métricas fornecidas pelos clientes. Na terminologia de grafite, uma métrica é qualquer quantidade mensurável que pode variar ao longo do tempo (como a utilização da CPU de um servidor ou o número de vendas de um produto). Um ponto de dados é simplesmente um par (timestamp, value) correspondente ao valor medido de uma métrica específica em um ponto no tempo. As métricas são identificadas de forma exclusiva por seu nome, e o nome de cada métrica, bem como seus pontos de dados, são fornecidos por aplicativos do cliente. Um tipo comum de aplicação de cliente é um agente de monitoramento que coleciona métricas de sistema ou aplicativo e envia seus valores coletados para carbono para fácil armazenamento e visualização. As métricas em grafite têm nomes hierárquicos simples, semelhantes aos caminhos do sistema de arquivos, exceto que um ponto é usado para delimitar a hierarquia em vez de uma barra ou barra invertida. O carbono respeitará qualquer nome legal e criará um arquivo sussurro para cada métrica para armazenar seus pontos de dados. Os arquivos de sussurro são armazenados dentro do diretório de dados de carbono s em uma hierarquia de sistema de arquivos que reflete a hierarquia delimitada por pontos em cada nome de métricas, de modo que (por exemplo) servers. www01.cpuUsage mapeia para hellipserverswww01cpuUsage. wsp. Quando um aplicativo cliente deseja enviar pontos de dados para Grafite, ele deve estabelecer uma conexão TCP ao carbono. Geralmente na porta 2003 2. O cliente faz todo o carbono que fala não envia nada sobre a conexão. O cliente envia pontos de dados em um formato simples de texto simples enquanto a conexão pode ser aberta e reutilizada conforme necessário. O formato é uma linha de texto por ponto de dados em que cada linha contém o nome da métrica pontilhada, o valor e um carimbo de data / hora Unix separados por espaços. Por exemplo, um cliente pode enviar: Em um nível alto, todo o carbono é ouvir dados neste formato e tentar armazená-lo no disco o mais rápido possível usando sussurro. Mais tarde, vamos discutir os detalhes de alguns truques usados ​​para garantir a escalabilidade e obter o melhor desempenho que podemos obter de um disco rígido típico. 7.3. The Front End: Graphs On-Demand O webapp grafite permite aos usuários solicitar gráficos personalizados com uma simples API baseada em URL. Os parâmetros de representação gráfica são especificados na seqüência de consulta de uma solicitação HTTP GET e uma imagem PNG é retornada em resposta. Por exemplo, o URL: solicita um gráfico 500times300 para a métrica servers. www01.cpuUsage e as últimas 24 horas de dados. Na verdade, apenas o parâmetro alvo é necessário, todos os outros são opcionais e usam seus valores padrão se forem omitidos. A grafite suporta uma grande variedade de opções de exibição, bem como funções de manipulação de dados que seguem uma simples sintaxe funcional. Por exemplo, podemos representar uma média móvel de 10 pontos da métrica em nosso exemplo anterior, como este: as funções podem ser aninhadas, permitindo expressões e cálculos complexos. Aqui está outro exemplo que dá o total total de vendas para o dia usando métricas por produto de vendas por minuto: a função sumSeries calcula uma série de tempo que é a soma de cada métrica que combina os produtos de padrão..salesPerMinute. Então integral calcula um total em execução em vez de uma contagem por minuto. A partir daqui, não é muito difícil imaginar como construir uma interface de usuário da web para visualizar e manipular gráficos. Grafite vem com sua própria UI compositor, mostrada na Figura 7.3. Isso faz isso usando o Javascript para modificar os parâmetros de URL dos gráficos à medida que o usuário clica nos menus dos recursos disponíveis. Figura 7.3: Interface do Compositor Graphites 7.4. Dashboards Desde a sua criação Graphite tem sido usado como uma ferramenta para criar painéis baseados na web. A URL API torna este um caso de uso natural. Fazer um painel é tão simples como fazer uma página HTML cheia de tags como esta: no entanto, nem todos gostam de criar URLs manualmente, portanto Graphites Composer UI fornece um método de apontar e clicar para criar um gráfico a partir do qual você pode simplesmente copiar e Cole o URL. Quando combinado com outra ferramenta que permite a criação rápida de páginas da web (como um wiki), isso torna-se bastante fácil para que usuários não-técnicos possam criar facilmente seus próprios painéis. 7.5. Um gargalo obvio Uma vez que meus usuários começaram a construir painéis, Graphite rapidamente começou a ter problemas de desempenho. Eu investiguei os logs do servidor web para ver quais solicitações estavam atrapalhando. Era bem óbvio que o problema era o grande número de solicitações gráficas. O webapp estava ligado à CPU, representando gráficos constantemente. Notei que havia muitos pedidos idênticos, e os painéis eram culpados. Imagine que você tem um painel com 10 gráficos e a página é atualizada uma vez por minuto. Cada vez que um usuário abre o painel em seu navegador, Graphite tem que lidar com mais 10 pedidos por minuto. Isso rapidamente se torna caro. Uma solução simples é renderizar cada gráfico apenas uma vez e depois enviar uma cópia para cada usuário. A estrutura web do Django (com o qual Graphite é construído) fornece um excelente mecanismo de cache que pode usar vários back-ends como o memcached. Memcached 3 é essencialmente uma tabela hash fornecida como um serviço de rede. Os aplicativos de clientes podem obter e definir pares de valores-chave como uma tabela de hash comum. O principal benefício do uso do memcached é que o resultado de uma solicitação cara (como renderizar um gráfico) pode ser armazenado muito rapidamente e recuperado posteriormente para lidar com pedidos subsequentes. Para evitar retornar os mesmos gráficos obsoletos para sempre, o memcached pode ser configurado para expirar os gráficos em cache após um curto período. Mesmo que este seja apenas alguns segundos, o peso que tira da grafite é tremendo porque os pedidos duplicados são tão comuns. Outro caso comum que cria muitos pedidos de renderização é quando um usuário está ajustando as opções de exibição e aplicando funções na interface do usuário Composer. Cada vez que o usuário muda algo, Graphite deve redesenhar o gráfico. Os mesmos dados estão envolvidos em cada pedido, por isso faz sentido colocar os dados subjacentes no memcache também. Isso mantém a UI responsiva ao usuário porque a etapa de recuperar dados é ignorada. 7.6. Otimizando o IO Imagine que você possui 60.000 métricas que você envia para o seu servidor de grafite e cada uma dessas métricas tem um ponto de dados por minuto. Lembre-se de que cada métrica possui seu próprio arquivo de sussurro no sistema de arquivos. Isso significa que o carbono deve fazer uma operação de gravação para 60.000 arquivos diferentes a cada minuto. Enquanto o carbono pode escrever em um arquivo cada milissegundo, ele poderá continuar. Isso não é muito procurado, mas dizemos que você tem 600.000 métricas atualizando cada minuto, ou suas métricas estão atualizando a cada segundo, ou talvez você simplesmente não possa pagar o armazenamento rápido e suficiente. Seja qual for o caso, suponha que a taxa de pontos de dados recebidos exceda a taxa de operações de gravação que seu armazenamento pode acompanhar. Como essa situação deve ser tratada. A maioria dos discos rígidos atualmente tem tempo de busca lento 4. isto é, o atraso entre fazer operações de IO em dois locais diferentes, em comparação com a escrita de uma seqüência contígua de dados. Isso significa a escrita mais contígua que fazemos, quanto mais o resultado obtemos. Mas se tivermos milhares de arquivos que precisam ser escritos com freqüência, e cada gravação é muito pequena (um ponto de dados de sussurro é de apenas 12 bytes), então nossos discos definitivamente passarão a maior parte do tempo procurando. Trabalhando sob o pressuposto de que a taxa de operações de gravação tem um teto relativamente baixo, a única maneira de aumentar nosso throughput do ponto de dados além dessa taxa é escrever múltiplos pontos de dados em uma única operação de gravação. Isso é viável porque o sussurro organiza pontos de dados consecutivos de forma contígua no disco. Então eu adicionei uma atualização de função para sussurrar. Que leva uma lista de pontos de dados para uma única métrica e compacta pontos de dados contíguos em uma única operação de gravação. Mesmo que isso tenha tornado cada uma escrita maior, a diferença de tempo necessária para escrever dez pontos de dados (120 bytes) versus um ponto de dados (12 bytes) é insignificante. Demora mais alguns pontos de dados antes que o tamanho de cada gravação comece a afetar significativamente a latência. Em seguida, implementei um mecanismo de buffer em carbono. Cada ponto de dados recebido é mapeado para uma fila com base em seu nome de métrica e, em seguida, é anexado a essa fila. Outro segmento repetidamente itera através de todas as filas e para cada um que puxa todos os dados apontar e os grava no arquivo de sussurro apropriado com updatemany. Voltando ao nosso exemplo, se tivermos 600.000 métricas atualizando a cada minuto e nosso armazenamento só pode acompanhar 1 gravação por milissegundo, então as filas acabarão segurando aproximadamente 10 pontos de dados em média. O único recurso que isso nos custa é a memória, que é relativamente abundante, pois cada ponto de dados é apenas alguns bytes. Essa estratégia protege dinamicamente tantos pontos de dados quanto necessário para manter uma taxa de datapoints recebidos que podem exceder a taxa de operações de IO que seu armazenamento pode acompanhar. Uma boa vantagem dessa abordagem é que ele acrescenta um grau de resiliência para lidar com desaceleração temporária de IO. Se o sistema precisar fazer outros trabalhos de IO fora do Graphite, é provável que a taxa de operações de gravação diminua, caso em que as filas de carbono simplesmente crescerão. Quanto maiores as filas, maiores as gravações. Uma vez que o rendimento global dos pontos de dados é igual à taxa de tempos de operações de escrita, o tamanho médio de cada escrita, o carbono pode manter-se enquanto haja memória suficiente para as filas. O mecanismo de enfileiramento de carbono s é representado na Figura 7.4. Figura 7.4: Mecanismo de enfileiramento de carvões 7.7. Mantendo-o em tempo real, os pontos de dados de buffer foram uma ótima maneira de otimizar o carbono IO, mas não demorou muito para que meus usuários notassem um efeito colateral bastante preocupante. Revisando nosso exemplo novamente, obtivemos 600 mil métricas que atualizamos cada minuto e assumimos que nosso armazenamento só pode acompanhar 60 mil operações de gravação por minuto. Isso significa que teremos aproximadamente 10 minutos de dados sentados em filas de Carbono a qualquer momento. Para um usuário, isso significa que os gráficos que eles solicitam do webapp grafite perderão os últimos 10 minutos de dados: Não é bom. A solução é bastante direta. Simplesmente adicionei um ouvinte de soquete ao carbono que fornece uma interface de consulta para acessar os pontos de dados armazenados e, em seguida, modifica o webapp grafite para usar essa interface sempre que precisa recuperar dados. O webapp combina os pontos de dados que recupera do carbono com os pontos de dados recuperados do disco e voila, os gráficos são em tempo real. Concedido, no nosso exemplo, os pontos de dados são atualizados ao minuto e, portanto, não exatamente em tempo real, mas o fato de que cada ponto de dados é acessível instantaneamente em um gráfico uma vez que é recebido pelo carbono é em tempo real. 7.8. Kernels, Caches e Catastrophic Failures Como provavelmente é óbvio até agora, uma característica chave do desempenho do sistema que o desempenho próprio do Graphites depende da latência de IO. Até o momento, assumimos que o nosso sistema tem consistentemente baixa latência de IO com uma média de 1 milissegundo por gravação, mas essa é uma grande hipótese que requer uma análise um pouco mais profunda. A maioria dos discos rígidos simplesmente não é rápido, mesmo com dezenas de discos em uma matriz RAID, é provável que tenha mais de 1 milissegundo de latência para acesso aleatório. No entanto, se você tentasse testar a rapidez com que até um laptop antigo pudesse escrever um kilobyte inteiro no disco, você acharia que a chamada do sistema de gravação retorna em muito menos de 1 milissegundo. Por que, sempre que o software possui características de desempenho incoerentes ou inesperadas, geralmente o armazenamento em buffer ou o armazenamento em cache são culpados. Neste caso, estavam lidando com ambos. A chamada do sistema de gravação não técnico escreve seus dados no disco, ele simplesmente o coloca em um buffer que o kernel então grava no disco mais tarde. É por isso que a chamada de gravação geralmente retorna tão rapidamente. Mesmo após o buffer ter sido gravado no disco, ele geralmente permanece em cache para leituras subseqüentes. Ambos os comportamentos, armazenamento em buffer e armazenamento em cache, exigem memória, é claro. Os desenvolvedores do Kernel, sendo as pessoas inteligentes que são, decidiram que seria uma boa idéia usar qualquer memória do espaço do usuário atualmente livre ao invés de alocar a memória de forma definitiva. Isso acaba por ser um impulsionador de desempenho tremendamente útil e também explica por que, não importa a quantidade de memória que você adiciona a um sistema, geralmente acabará por ter uma memória livre quase zero depois de fazer uma quantidade modesta de IO. Se as suas aplicações de espaço de usuário não estão usando essa memória, provavelmente o seu kernel. A desvantagem dessa abordagem é que essa memória livre pode ser tirada do kernel no momento em que uma aplicação de espaço de usuário decide que precisa alocar mais memória para si. A semente não tem escolha senão renunciá-lo, perdendo quaisquer tampões que haja estado lá. Então, o que tudo isso significa para a grafite. Nós simplesmente destacamos a confiança do carbono em uma latência de IO consistentemente baixa e também sabemos que a chamada do sistema de gravação só retorna rapidamente porque os dados estão sendo copiados apenas para um buffer. O que acontece quando não há memória suficiente para o kernel para continuar as gravações de buffer. As gravações se tornam síncronas e, portanto, terrivelmente lentas Isso causa uma queda dramática na taxa de operações de gravação de carbono, o que faz com que as filas de carbono s cresçam, o que come ainda mais Memória, morrendo de fome o kernel ainda mais. No final, esse tipo de situação geralmente resulta em carbono ficando sem memória ou sendo morto por um sysadmin irritado. Para evitar esse tipo de catástrofe, adicionei vários recursos ao carbono, incluindo limites configuráveis ​​sobre quantos pontos de dados podem ser enfileirados e limites de taxa de velocidade com que várias operações de sussurro podem ser executadas. Esses recursos podem proteger o carbono de fora de controle e, em vez disso, impor efeitos menos severos, como deixar alguns pontos de dados ou se recusar a aceitar mais pontos de dados. No entanto, os valores adequados para essas configurações são específicos do sistema e exigem uma quantidade razoável de testes para sintonizar. Eles são úteis, mas eles não resolvem o problema de forma fundamental. Para isso, é preciso mais hardware. 7.9. Clustering Fazer múltiplos servidores de grafite parece ser um sistema único, do ponto de vista do usuário, não é extremamente difícil, pelo menos para uma implementação naiumlve. A interação do usuário do webapps consiste principalmente em duas operações: encontrar métricas e obter pontos de dados (geralmente na forma de um gráfico). As operações de busca e busca do webapp estão escondidas em uma biblioteca que abstrai sua implementação do resto da base de código e também são expostas através de manipuladores de solicitação HTTP para chamadas remotas fáceis. A operação de busca procura o sistema de arquivos local de dados de sussurro para coisas que correspondem a um padrão especificado pelo usuário, assim como um sistema de arquivos glob como. txt corresponde a arquivos com essa extensão. Sendo uma estrutura de árvore, o resultado retornado pelo achado é uma coleção de objetos de nó, cada um derivado das sub-classes de filial ou Folha de Nó. Os diretórios correspondem a nós de ramificação e os arquivos de sussurro correspondem a nós de folha. Esta camada de abstração facilita o suporte a diferentes tipos de armazenamento subjacente, incluindo arquivos RRD 5 e arquivos de sussurros gzip. A interface Leaf define um método de busca cuja implementação depende do tipo de nó da folha. No caso de arquivos sussurros, é simplesmente um invólucro fino em torno da própria função de busca da biblioteca sussurros. Quando o suporte ao agrupamento foi adicionado, a função de busca foi estendida para poder fazer chamadas de busca remota via HTTP para outros servidores de grafite especificados na configuração do webapps. Os dados do nó contidos nos resultados dessas chamadas HTTP são envolvidos como objetos RemoteNode que estão em conformidade com o Nó usual. Ramo. E Folhas. Isso torna o cluster transparente para o resto da base de código do webapps. O método de busca para um nó de folha remota é implementado como outra chamada HTTP para recuperar os pontos de dados do servidor de grafites de nós. Todas essas chamadas são feitas entre os webapps da mesma forma que um cliente os chamaria, exceto com um parâmetro adicional especificando que a operação deveria ser realizada localmente e não redistribuída em todo o cluster. Quando o webapp é solicitado a renderizar um gráfico, ele realiza a operação de busca para localizar as métricas solicitadas e as chamadas buscarem em cada uma para recuperar seus pontos de dados. Isso funciona se os dados estão no servidor local, servidores remotos ou ambos. Se um servidor for baixado, o controle remoto expira bastante rápido e o servidor está marcado como fora de serviço por um curto período durante o qual nenhuma outra ligação será feita. Do ponto de vista do usuário, qualquer um dos dados no servidor perdido estará faltando nos seus gráficos, a menos que esses dados estejam duplicados em outro servidor no cluster. 7.9.1. Uma Breve Análise da Eficiência de Clustering A parte mais cara de uma solicitação gráfica está representando o gráfico. Cada renderização é realizada por um único servidor para adicionar mais servidores efetivamente aumentar a capacidade de renderização de gráficos. No entanto, o fato de que muitos pedidos acabam distribuindo encontrar chamadas para todos os outros servidores no cluster significa que nosso esquema de agrupamento compartilha muito da carga frontal, em vez de dispersá-lo. O que conseguimos neste momento, no entanto, é uma maneira eficaz de distribuir a carga de back-end, pois cada instância de carbono opera de forma independente. Este é um bom primeiro passo, já que a maior parte do tempo o back-end é um gargalo muito antes do front-end, mas claramente o front-end não escalará horizontalmente com essa abordagem. Para tornar a escala de frente mais efetiva, o número de chamadas de busca remota feitas pelo webapp deve ser reduzido. Novamente, a solução mais fácil é o cache. Assim como o memcached já é usado para armazenar em cache pontos de dados e gráficos renderizados, ele também pode ser usado para armazenar em cache os resultados das solicitações de pesquisa. Uma vez que a localização das métricas é muito menos provável que mude com frequência, isso normalmente deve ser armazenado em cache por mais tempo. O trade-off da configuração do tempo limite do cache para encontrar resultados muito longos, porém, é que novas métricas que foram adicionadas à hierarquia podem não aparecer tão rapidamente para o usuário. 7.9.2. Distribuindo Métricas em um Cluster O webapp grafite é bastante homogêneo em todo um cluster, na medida em que executa exatamente o mesmo trabalho em cada servidor. O papel do carbono, no entanto, pode variar de servidor para servidor, dependendo dos dados que você escolher para enviar para cada instância. Muitas vezes, existem muitos clientes diferentes enviando dados para o carbono. Então seria bastante irritante acoplar cada configuração de clientes com seu layout de clusters de grafite. As métricas de aplicativos podem ir para um servidor de carbono, enquanto as métricas de negócios podem ser enviadas para vários servidores de carbono para redundância. Para simplificar o gerenciamento de cenários como este, Graphite vem com uma ferramenta adicional chamada de retransmissão de carbono. Seu trabalho é bastante simples, ele recebe dados métricos de clientes exatamente como o daemon de carbono padrão (que é realmente chamado de carbono-cache), mas ao invés de armazenar os dados, ele aplica um conjunto de regras aos nomes das métricas para determinar quais servidores de cache de carbono Para retransmitir os dados para. Cada regra consiste em uma expressão regular e uma lista de servidores de destino. Para cada ponto de dados recebido, as regras são avaliadas em ordem e a primeira regra cuja expressão regular corresponde ao nome da métrica é usada. Desta forma, todos os clientes precisam fazer é enviar seus dados para o retransmissão de carbono e acabará nos servidores certos. Em certo sentido, o retransmissão de carbono fornece funcionalidade de replicação, embora seja mais precisamente chamado de duplicação de entrada, uma vez que não trata de problemas de sincronização. Se um servidor for desativado temporariamente, faltará os pontos de dados para o período de tempo em que estava desligado, mas, de outra forma, funcionou normalmente. Existem scripts administrativos que deixam o controle do processo de re-sincronização nas mãos do administrador do sistema. 7.10. Reflexões de design Minha experiência em trabalhar na Graphite reafirmou a crença de que a escalabilidade tem muito pouco a ver com desempenho de baixo nível, mas é um produto do design geral. Eu já encontrei muitos estrangulamentos ao longo do caminho, mas cada vez que busco melhorias em design, em vez de acelerar o desempenho. Foi-me perguntado muitas vezes por que escrevi grafite em Python em vez de Java ou C, e minha resposta é sempre que ainda tenho que encontrar uma verdadeira necessidade do desempenho que outro idioma poderia oferecer. Em Knu74, Donald Knuth disse que a otimização prematura é a raiz de todo o mal. Enquanto assumirmos que o nosso código continuará evoluindo de maneiras não triviais, então toda otimização 6 é, de certa forma, prematura. Um dos grafites maiores forças e maiores fraquezas é o fato de que muito pouco disso foi realmente projetado no sentido tradicional. Em geral, a grafite evoluiu gradualmente, obstáculo ao obstáculo, à medida que surgem problemas. Muitas vezes os obstáculos eram previsíveis e várias soluções preventivas pareciam naturais. No entanto, pode ser útil evitar resolver problemas que você ainda não tem ainda, mesmo que pareça provável que você em breve. A razão é que você pode aprender muito mais de estudar de perto as falhas reais do que teorizar sobre estratégias superiores. A resolução de problemas é conduzida tanto pelos dados empíricos que temos em mãos quanto pelo nosso próprio conhecimento e intuição. Descobri que duvidar de sua própria sabedoria o suficiente pode forçá-lo a olhar mais detalhadamente seus dados empíricos. Por exemplo, quando eu escrevi pela primeira vez, eu estava convencido de que deveria ser reescrito em C para velocidade e que minha implementação do Python seria apenas um protótipo. Se eu estivesse de acordo com uma crise de tempo, eu poderia ter ignorado completamente a implementação do Python. Acontece, no entanto, que o IO é um gargalo muito anterior à CPU, que a menor eficiência de Python dificilmente importa na prática. Como eu disse, porém, a abordagem evolutiva também é uma grande fraqueza da grafite. Interfaces, afinal, não se prestam bem à evolução gradual. Uma boa interface é consistente e emprega convenções para maximizar a previsibilidade. Por esta medida, a API de URL de grafites é atualmente uma interface de sub-par na minha opinião. Opções e funções foram adotadas ao longo do tempo, às vezes formando pequenas ilhas de consistência, mas, em geral, não possuem um senso global de consistência. A única maneira de resolver esse problema é através da versão de interfaces, mas isso também tem inconvenientes. Uma vez que uma nova interface é projetada, a antiga ainda é difícil de se livrar, permanecendo como bagagem evolucionária como o apêndice humano. Pode parecer inofensivo o suficiente até que um dia seu código obtenha apendicite (ou seja, um erro vinculado à interface antiga) e você está obrigado a operar. Se eu mudasse uma coisa sobre Graphite no início, teria sido ter muito mais cuidado na concepção das APIs externas, pensando em vez de evoluí-las pouco a pouco. Outro aspecto da grafite que causa alguma frustração é a flexibilidade limitada do modelo hierárquico de nomenclatura métrica. Embora seja bastante simples e muito conveniente para a maioria dos casos de uso, torna complicadas as consultas sofisticadas, mesmo impossíveis. Quando pensei inicialmente em criar Graphite, eu sabia desde o início que queria uma API de URL editável por humanos para criar gráficos 7. Enquanto ainda me agrada que grafite forneça isso hoje, receio que esse requisito tenha sobrecarregado a API com uma sintaxe excessivamente simples que Faz expressões complexas pesadas. Uma hierarquia torna o problema de determinar a chave primária para uma métrica bastante simples porque um caminho é essencialmente uma chave primária para um nó na árvore. A desvantagem é que todos os dados descritivos (ou seja, dados da coluna) devem ser incorporados diretamente no caminho. Uma solução potencial é manter o modelo hierárquico e adicionar um banco de dados de metadados separado para permitir uma seleção mais avançada de métricas com uma sintaxe especial. 7.11. Tornando-se de código aberto Olhando para a evolução da grafite, ainda estou surpreso por quão longe ele veio como um projeto e por quão longe me levou como programador. Começou como um projeto de estimação que era apenas algumas centenas de linhas de código. O mecanismo de renderização começou como uma experiência, simplesmente para ver se eu poderia escrever um. O sussurro foi escrito no decorrer de um fim de semana fora do desespero para resolver um problema de show-stopper antes de uma data crítica de lançamento. O carbono foi reescrito mais vezes do que eu me lembrava. Uma vez que eu tenha permissão para liberar Grafite sob uma licença de código aberto em 2008, nunca esperei muita resposta. Depois de alguns meses, foi mencionado em um artigo CNET que foi retirado pela Slashdot e o projeto de repente decolou e tem estado ativo desde então. Hoje, existem dezenas de grandes e médias empresas que usam Graphite. A comunidade é bastante ativa e continua a crescer. Longe de ser um produto acabado, há um grande trabalho experimental que está sendo feito, o que mantém divertido trabalhar e cheio de potencial. Launchpad. netgraphite Existe outra porta sobre a qual os objetos serializados podem ser enviados, o que é mais eficiente que o formato de texto simples. Isso só é necessário para níveis muito altos de tráfego. Memcached. org As unidades de estado sólido geralmente têm tempos de busca extremamente rápidos em comparação com os discos rígidos convencionais. Os arquivos RRD são, na verdade, nós de ramificação porque eles podem conter várias fontes de dados, uma fonte de dados RRD é um nó de folha. Knuth especificamente significou otimização de código de baixo nível, não otimização macroscópica, como melhorias de design. Isso força os próprios gráficos a serem de código aberto. Qualquer um pode simplesmente olhar para um URL de gráficos para compreendê-lo ou modificá-lo.

No comments:

Post a Comment