Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

English

Servir

Um servidor guarda uma série e responde a pedidos pequenos sobre ela: a sua descrição, tiles para um gráfico no navegador e imagens. O protocolo é HTTP GET simples, então qualquer cliente, cache ou proxy o entende. O nonius-server é o servidor de referência, um programa que você instala pelo Cargo:

cargo install nonius-server

Este capítulo serve as leituras de Seus dados: um ponto por milissegundo durante 100 segundos, num CSV.

De um CSV a um servidor no ar

nonius-server csv readings.csv readings.nsb
nonius-server build readings.nsb readings.pyr.nsb --base-ns 1000000 --levels 4
nonius-server verify readings.pyr.nsb

A primeira linha escreve o arquivo de série. A segunda constrói um arquivo de pirâmide: a série e a sua pirâmide, guardadas como os tiles do protocolo, então um tile é lido direto dele. A terceira confere os hashes e constrói a pirâmide de novo para comparar. Cada uma diz o que fez:

readings.nsb: 100000 points from readings.csv; 2 decimal places, the most any value has; in time order
readings.pyr.nsb: 100000 points, 3 levels kept from level 1, 32810 buckets; 4.5 MB, 45.0 B a point

Os pontos estão a um milissegundo de distância, então a base é um milissegundo. O nível 0 teria um ponto por bucket, e foi liberado (veja O que custa): três níveis ficam.

Um servidor também pode servir o arquivo de série simples, construindo a pirâmide na memória ao iniciar. Um arquivo de pirâmide é construído uma vez e depois mapeado: o servidor inicia na hora, seja qual for o tamanho, e só as partes que um pedido lê vão para a memória.

nonius-server readings.pyr.nsb --id readings --addr 127.0.0.1:8080 &

O & o deixa rodando em segundo plano, para os comandos abaixo. O id de uma série é o nome do arquivo, a menos que --id dê outro; vários arquivos servem várias séries.

Perguntar a ele

A descrição da série, os seus metadados:

curl -s http://127.0.0.1:8080/v1/series/readings
{"protocol":1,"series":"readings","base_ns":"1000000","levels":4,"ratio":4,"tile_columns":2048,"raw_tile_ns":"4096000000","max_k":4096,"v_exponent":2,"rows":"100000","first_t":"1760000000000000000","last_t":"1760000099999000004","last":{"t":"1760000099999000004","v":"10099","w":"1"}}

Os inteiros de 64 bits são strings, porque números JSON perdem precisão depois de 2⁵³. O attachTiles do navegador lê isso primeiro, depois pede tiles: /v1/series/{id}/columns/{level}/{k}/{i} para resumos e /v1/series/{id}/raw/{i} para pontos. Os endereços e o conteúdo deles são as seções 4 e 5 do protocolo; o gráfico os calcula sozinho, e você nunca escreve um à mão.

Uma imagem dos 100 segundos inteiros, clara, com título e unidade:

image='http://127.0.0.1:8080/v1/series/readings/png?from=1760000000000000000&to=1760000100000000000&width=1600&height=600&ratio=2&theme=light&title=Readings&unit=%C2%B0C'
curl -s -o readings.png "$image"

from e to são o tempo mostrado, [from, to): o to não entra, então a série inteira termina no tempo do último ponto mais um, ou depois. width e height são os pixels do próprio PNG; ratio=2 desenha rótulos e linhas para uma tela de dois pixels do dispositivo por pixel CSS, então essa imagem preenche uma caixa de 800 × 300 numa tela assim. A unidade °C vai codificada com porcentagem, como o URLSearchParams do navegador escreve. O tema é escuro, a menos que venha theme=light. Todo parâmetro está na página do nonius-server; um que o servidor não conhece é ignorado, então um erro de digitação (timezone= em vez de tz=) volta em silêncio ao padrão.

Cache

Um tile ou uma imagem nunca muda: o mesmo endereço sempre responde os mesmos bytes. O servidor diz isso — Cache-Control: public, max-age=31536000, immutable — e dá a cada resposta um ETag, um hash dos seus bytes. Um cliente que já a tem pergunta com a etiqueta e recebe 304 Not Modified, sem corpo:

etag=$(curl -s -o /dev/null -w '%header{etag}' "$image")
curl -s -o /dev/null -w '%{http_code}\n' -H "If-None-Match: $etag" "$image"

Isso imprime 304. Então um navegador, um proxy ou uma CDN podem guardar tiles e imagens pelo tempo que quiserem. Os metadados são a exceção: dizem no-cache, porque uma série que cresce muda o seu último ponto.

Uma página em outra origem

Uma página servida de um endereço só lê um servidor em outro se o servidor permitir. O nonius-server permite qualquer página: toda resposta leva Access-Control-Allow-Origin: *, expõe o seu ETag e os cabeçalhos da imagem aos scripts (Access-Control-Expose-Headers), e Cross-Origin-Resource-Policy: cross-origin, então uma página que se isola para a memória compartilhada do feed ao vivo ainda consegue lê-lo.

Uma imagem também diz onde está o seu gráfico: Nonius-Plot: x y width height, o retângulo do gráfico nos pixels da imagem, e Nonius-Range: lo hi, os valores nas suas linhas de baixo e de cima. Uma página que mostra o PNG transforma um clique num tempo e num valor com eles, e pede ao /pick do servidor o ponto embaixo dele.

Em produção

O nonius-server é a referência do protocolo e um apoio de testes, não um servidor de produção: sem TLS, sem limite de conexões, uma thread por conexão. Diante de usuários, coloque-o atrás de um proxy reverso que cuide do TLS e limite as conexões; como toda resposta, menos os metadados, é imutável, o proxy pode guardar todas em cache.

Para um servidor seu, dois caminhos:

  • O protocolo dentro do seu programa Rust, pela biblioteca do crate:
#![allow(unused)]
fn main() {
let served = Served::new("day", (t, v, w), 2, Options::default())?;
}

served.answer(&request) responde a um pedido sem socket, e serve o coloca num TcpListener; a página do crate mostra os dois.

  • O protocolo em qualquer linguagem. Ele foi escrito para ser implementado sem o código do Nonius: o protocolo dá cada endereço, byte e regra, e as imagens são desenhadas pelo pacote .NET como pelo Rust.