Configuração do verniz para armazenar em cache somente usuários não logados

5

Eu tenho um aplicativo Ruby on Rails liderado por verniz + nginx. Como a maior parte do conteúdo dos sites é estática, a menos que você seja um usuário logado, quero armazenar o site em cache intensamente com o verniz quando um usuário estiver desconectado, mas apenas para armazenar em cache os ativos estáticos quando eles estiverem conectados.

Quando um usuário está logado, ele terá o cookie 'user_credentials' presente no cabeçalho Cookie:, além disso, eu preciso pular o cache em / login e / sessions para que um usuário possa obter o cookie 'user_credentials' o primeiro lugar.

O Rails, por padrão, não define um cabeçalho de controle de Cache amigável ao cache, mas meu aplicativo define um cabeçalho "public, s-max-age = 60" quando um usuário não está conectado. Nginx está configurado para retornar 'expira cabeçalhos para todos os ativos estáticos.

A configuração que tenho no momento é totalmente ignorando o cache para tudo quando logado, incluindo ativos estáticos - e está retornando o cache MISS para tudo quando desconectado. Passei horas andando em círculos e aqui está meu default.vcl atual

    director rails_director round-robin {
  { 
    .backend = { 
      .host = "xxx.xxx.xxx.xxx"; 
      .port = "http";
      .probe = {
        .url = "/lbcheck/lbuptest";
        .timeout = 0.3 s;
        .window = 8;
        .threshold = 3;
      }
    } 
  }
}

sub vcl_recv {

  if (req.url ~ "^/login") {
    pipe;
  }

  if (req.url ~ "^/sessions") {
    pipe;
  }
  # The regex used here matches the standard rails cache buster urls
  # e.g. /images/an-image.png?1234567
  if (req.url ~ "\.(css|js|jpg|jpeg|gif|ico|png)\??\d*$") {
    unset req.http.cookie;
    lookup;
  } else {
    if (req.http.cookie ~ "user_credentials") {
      pipe;
    }
  }

  # Only cache GET and HEAD requests
  if (req.request != "GET" && req.request != "HEAD") {
    pipe;
  }

}

sub vcl_fetch {

  if (req.url ~ "^/login") {
    pass;
  }

  if (req.url ~ "^/sessions") {
    pass;
  }

  if (req.http.cookie ~ "user_credentials") {
    pass;
  } else {
    unset req.http.Set-Cookie;
  }

  # cache CSS and JS files
  if (req.url ~ "\.(css|js|jpg|jpeg|gif|ico|png)\??\d*$") {
    unset req.http.Set-Cookie;
  } 

  if (obj.status >=400 && obj.status <500) {
    error 404 "File not found";
  }

  if (obj.status >=500 && obj.status <600) {
    error 503 "File is Temporarily Unavailable";
  }

}

sub vcl_deliver {
  if (obj.hits > 0) {
          set resp.http.X-Cache = "HIT";
  } else {
          set resp.http.X-Cache = "MISS";
  }
}
    
por davidsmalley 17.07.2009 / 16:57

2 respostas

6

Ok, no final, consegui resolver isso usando o seguinte arquivo vcl. Observe que adicionei alguns bits extras para permitir a expiração do cache quando o backend morreu.

Parece que minha principal falha foi usar unset req.http.Set-Cookie; quando deveria estar usando unset obj.http.Set-Cookie; na seção vcl_fetch . ( obj em vcl_fetch e req na seção vcl_recv).

director rails_director round-robin {
  { 
    .backend = { 
      .host = "xxx.xxx.xxx.xxx"; 
      .port = "http";
      .probe = {
        .url = "/lbcheck/lbuptest";
        .timeout = 0.3 s;
        .window = 8;
        .threshold = 3;
      }
    } 
  }
}

sub vcl_recv {

  if (req.backend.healthy) {
    set req.grace = 30s;
  } else {
    set req.grace = 1h;
  }

  if (req.url ~ "^/login") {
    pipe;
  }

  if (req.url ~ "^/sessions") {
    pipe;
  }

  if (req.url ~ "\.(css|js|jpg|jpeg|gif|ico|png)\??\d*$") {
    unset req.http.cookie;
    lookup;
  } else {
    if (req.http.cookie ~ "user_credentials") {
      pipe;
    } else {
      unset req.http.cookie;
    }
  }

  # Only cache GET and HEAD requests
  if (req.request != "GET" && req.request != "HEAD") {
    pipe;
  }

}

sub vcl_fetch {

  set obj.grace = 1h;

  if (req.url ~ "^/login") {
    pass;
  }

  if (req.url ~ "^/sessions") {
    pass;
  }

  if (req.http.cookie ~ "user_credentials") {
    pass;
  } else {
    unset obj.http.Set-Cookie;
  }

  # cache CSS and JS files
  if (req.url ~ "\.(css|js|jpg|jpeg|gif|ico|png)\??\d*$") {
    unset obj.http.Set-Cookie;
  } 

  if (obj.status >=400 && obj.status <500) {
    error 404 "File not found";
  }

  if (obj.status >=500 && obj.status <600) {
    error 503 "File is Temporarily Unavailable";
  }

}

sub vcl_deliver {
  if (obj.hits > 0) {
          set resp.http.X-Cache = "HIT";
  } else {
          set resp.http.X-Cache = "MISS";
  }
}
    
por 17.07.2009 / 17:55
0

Não posso comentar, por isso estou postando isso como uma resposta.

Atenção: A partir de 2.1.0, obj. * é chamado beresp. * em vcl_fetch e obj. * agora é somente leitura.

Estes também parecem melhor colocados em vcl_recv em vez de vcl_fetch:

  if (req.url ~ "^/login") {
    pipe;
  }

  if (req.url ~ "^/sessions") {
    pipe;
  }

Por último, na sua definição de backend, eu adicionaria

.max_connections = 32;

Ajuste o número de back-ends de passageiros que você permitiu que o nginx / apache criasse. Se você não definir esse limite, deverá ficar de olho na sua fila global de passageiros (supondo que esteja usando passageiro).

    
por 09.06.2010 / 23:26