<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: jonas-elias</title>
    <description>The latest articles on DEV Community by jonas-elias (@jonas-elias).</description>
    <link>https://dev.to/jonas-elias</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1391097%2F1062ef61-c1a6-485a-a2ef-6c20552ac3d5.jpeg</url>
      <title>DEV Community: jonas-elias</title>
      <link>https://dev.to/jonas-elias</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jonas-elias"/>
    <language>en</language>
    <item>
      <title>KEDA HTTP Add-on: Escalonamento Dinâmico por Volume de Requisições</title>
      <dc:creator>jonas-elias</dc:creator>
      <pubDate>Fri, 28 Nov 2025 14:57:36 +0000</pubDate>
      <link>https://dev.to/jonas-elias/keda-http-add-on-escalonamento-dinamico-por-volume-de-requisicoes-3d88</link>
      <guid>https://dev.to/jonas-elias/keda-http-add-on-escalonamento-dinamico-por-volume-de-requisicoes-3d88</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;O escalonamento tradicional baseado em CPU ou memória atende bem a diversos cenários, mas pode apresentar limitações em aplicações que sofrem bursts de requisições ou que exibem padrões de tráfego irregulares. Nesses casos, é comum que a aplicação mantenha níveis estáveis de CPU e memória ao mesmo tempo que enfrenta pressão direta no atendimento HTTP, gerando aumento de latência, formação de filas e redução de throughput antes que o autoscaler identifique a necessidade de ajuste.&lt;/p&gt;

&lt;p&gt;O KEDA HTTP Add-on foi desenvolvido para lidar com essas situações ao permitir que o escalonamento considere o volume de requisições como métrica primária. Essa abordagem oferece uma resposta mais alinhada ao comportamento real da carga, especialmente em serviços sensíveis a variações rápidas de demanda ou que dependem de tempo de reação reduzido.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como o Keda HTTP Add-on funciona?
&lt;/h2&gt;

&lt;p&gt;O Keda HTTP Add-on é composto por quatro elementos principais, cada um com responsabilidades específicas dentro do fluxo de escalonamento baseado em requisições HTTP.&lt;/p&gt;

&lt;p&gt;Operador – Responsável por observar eventos relacionados a HTTPScaledObjects. A partir dessas mudanças, cria, ajusta ou remove os recursos internos necessários para manter o comportamento de escalonamento.&lt;/p&gt;

&lt;p&gt;Interceptor – Atua como ponto de entrada do tráfego HTTP. Ele recebe requisições externas, aplica o roteamento adequado e encaminha cada chamada para a aplicação interna correspondente.&lt;/p&gt;

&lt;p&gt;Scaler – Monitora continuamente o volume de requisições pendentes associadas a uma aplicação. Com base nessa observação, reporta métricas para o KEDA utilizando o mecanismo de external scaler, permitindo que a decisão de escalonamento seja baseada diretamente no acúmulo de requisições.&lt;/p&gt;

&lt;p&gt;KEDA – Opera como o escalador responsável por ajustar a quantidade de réplicas da aplicação HTTP. Ele utiliza os dados fornecidos pelo scaler para determinar quando aumentar ou reduzir o número de instâncias.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8h4swa67wjcby9jz188.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8h4swa67wjcby9jz188.png" alt=" " width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Como utilizar o componente?
&lt;/h2&gt;

&lt;p&gt;A utilização do KEDA HTTP Add-on envolve alguns elementos dentro do ambiente Kubernetes. No contexto deste artigo, trabalharemos com o seguinte conjunto:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Aplicação PHP executando em Kubernetes&lt;br&gt;
Uma aplicação HTTP, empacotada em container e implantada como um Deployment, servindo como base para observar o comportamento do escalonamento.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deployment configurado para scale-to-zero&lt;br&gt;
A configuração define que a aplicação pode ser reduzida a zero réplicas quando o tráfego estiver ocioso, permitindo observar o comportamento de inicialização sob demanda.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KEDA HTTP Add-on como ponto de interceptação&lt;br&gt;
O add-on recebe o tráfego externo, gerencia a fila de requisições e garante que chamadas sejam corretamente encaminhadas ao serviço, independentemente do estado atual das réplicas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Escalonamento orientado à demanda&lt;br&gt;
Com o scaler monitorando as requisições pendentes, o KEDA ajusta o número de réplicas conforme o acúmulo ou redução do tráfego.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Atendimento de requisições mesmo com a aplicação inativa&lt;br&gt;
O interceptor mantém uma fila temporária, permitindo que requisições recebam resposta mesmo quando o Deployment está em zero réplicas, enquanto o sistema inicia automaticamente novas instâncias.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Temos também alguns pré-requisitos a nível de ferramentas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker (Desktop ou Engine)&lt;/li&gt;
&lt;li&gt;Kubernetes configurado (kind ou Minikube)&lt;/li&gt;
&lt;li&gt;Kubectl instalado&lt;/li&gt;
&lt;li&gt;Helm instalado&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Após todas instaladas e configuradas corretamente, é possível prosseguir.&lt;/p&gt;

&lt;p&gt;1 - Criar a aplicação PHP&lt;/p&gt;

&lt;p&gt;Crie um arquivo &lt;code&gt;index.php&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_SERVER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'REQUEST_URI'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="s1"&gt;'/ping'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"pong"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello from PHP!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Crie o Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; php:8.3-cli&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; index.php /var/www/html/index.php&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["php", "-S", "0.0.0.0:8080", "-t", "/var/www/html"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Faça o build localmente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;minikube docker-env&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="c"&gt;# caso esteja utilizando o minikube&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; keda-php-demo:latest &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 - Criar o Deployment + Service&lt;/p&gt;

&lt;p&gt;Arquivo &lt;code&gt;deployment.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keda-php-demo&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keda-php-demo&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keda-php-demo&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keda-php-demo&lt;/span&gt;
          &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keda-php-demo:latest&lt;/span&gt;
          &lt;span class="na"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Never&lt;/span&gt;
          &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keda-php-demo&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keda-php-demo&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
      &lt;span class="na"&gt;targetPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aplicar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; deployment.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3 - Instalar o KEDA&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm repo add kedacore https://kedacore.github.io/charts
helm repo update
helm &lt;span class="nb"&gt;install &lt;/span&gt;keda kedacore/keda &lt;span class="nt"&gt;--namespace&lt;/span&gt; keda &lt;span class="nt"&gt;--create-namespace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;4 - Instalar o HTTP Add-on&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm &lt;span class="nb"&gt;install &lt;/span&gt;keda-addons-http kedacore/keda-add-ons-http &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; keda
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso instala:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP operator&lt;/li&gt;
&lt;li&gt;Interceptor Proxy (responsável por receber requisições)&lt;/li&gt;
&lt;li&gt;Scalers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;5 - Criar o HTTPScaledObject&lt;/p&gt;

&lt;p&gt;Arquivo &lt;code&gt;http-scaledobject.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http.keda.sh/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTPScaledObject&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keda-php-demo&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;php-demo.local&lt;/span&gt;
  &lt;span class="na"&gt;pathPrefixes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/&lt;/span&gt;
  &lt;span class="na"&gt;scaleTargetRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keda-php-demo&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
    &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
    &lt;span class="na"&gt;service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;keda-php-demo&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
    &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
  &lt;span class="na"&gt;scaledownPeriod&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
  &lt;span class="na"&gt;scalingMetric&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;requestRate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;granularity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1s&lt;/span&gt;
      &lt;span class="na"&gt;targetValue&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
      &lt;span class="na"&gt;window&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1m&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Aplicar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; http-scaledobject.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;6 - Testando a aplicação&lt;/p&gt;

&lt;p&gt;Fazer port-forward do interceptor para acessar na máquina local:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl port-forward svc/keda-add-ons-http-interceptor-proxy &lt;span class="nt"&gt;-n&lt;/span&gt; keda 8081:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enviar requisição:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Host: php-demo.local"&lt;/span&gt; http://localhost:8081/ping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deve receber a resposta&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;pong&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Mesmo com réplicas = 0.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O KEDA:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Intercepta a requisição&lt;/li&gt;
&lt;li&gt;Sobe o pod automaticamente&lt;/li&gt;
&lt;li&gt;Encaminha a requisição quando o pod está pronto&lt;/li&gt;
&lt;li&gt;Escala conforme a fila de requisições&lt;/li&gt;
&lt;li&gt;Derruba tudo após scaledownPeriod: 30 segundos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OBS: É recomendável manter sempre réplicas ativas em ambientes de alto volume. Caso todas as réplicas cheguem a zero, o tempo necessário para que um novo POD/máquina fique saudável pode levar o solicitante a receber um Bad Gateway, o que acaba sendo contabilizado como indisponibilidade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analisando o dashboard do minikube
&lt;/h2&gt;

&lt;p&gt;Caso tenha optado pelo minikube, é possível observar o comportamento no dashboard através do comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;minikube dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após isso a seguinte página com os componentes do K8S será apresentada no navegador:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlqez519a28yxui3qbkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwlqez519a28yxui3qbkt.png" alt=" " width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Como o scaling realmente funciona?
&lt;/h2&gt;

&lt;p&gt;O HTTP Add-on não escala baseado em CPU e não escala baseado em RPS (Requests por Segundo).&lt;br&gt;
Ele usa o número de requisições pendentes na fila interna mantida pelo interceptor.&lt;/p&gt;

&lt;p&gt;Esse número representa quantas requisições ainda estão esperando ser atendidas pelos pods.&lt;/p&gt;

&lt;p&gt;O algoritmo usado é o mesmo algoritmo oficial do Kubernetes HPA, só que aplicado à métrica de requisições pendentes.&lt;/p&gt;

&lt;p&gt;A fórmula do HPA é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;desiredReplicas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;currentReplicas&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;pendingRequests&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;targetPendingRequests&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Onde:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pendingRequests&lt;/strong&gt; -&amp;gt; tamanho da fila interna&lt;br&gt;
&lt;strong&gt;targetPendingRequests&lt;/strong&gt; -&amp;gt; quantas requisições 1 pod deve conseguir suportar sem saturar&lt;br&gt;
&lt;strong&gt;currentReplicas&lt;/strong&gt; -&amp;gt; número atual de pods&lt;br&gt;
&lt;strong&gt;desiredReplicas&lt;/strong&gt; -&amp;gt; número final de pods após cálculo&lt;/p&gt;

&lt;p&gt;Suponha:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pendingRequests = 25&lt;/li&gt;
&lt;li&gt;targetPendingRequests = 10&lt;/li&gt;
&lt;li&gt;currentReplicas = 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Aplicando a fórmula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;desiredReplicas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;25&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;desiredReplicas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ceil&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;desiredReplicas&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ou seja: 3 réplicas são necessárias para esvaziar a fila mantendo ~10 requisições por pod.&lt;/p&gt;

&lt;p&gt;Esse comportamento é consistente, previsível e resistente a bursts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerações finais
&lt;/h2&gt;

&lt;p&gt;Esse setup demonstra como o KEDA HTTP Add-on permite construir serviços:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eficientes e responsivos&lt;/li&gt;
&lt;li&gt;Econômicos (scale-to-zero real)&lt;/li&gt;
&lt;li&gt;Independentes de métricas como CPU e memória&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Além disso, demonstra como é possível montar um ambiente completo em máquina local sem complexidade.&lt;/p&gt;

&lt;p&gt;O único ponto de atenção é que o componente ainda está em beta release (data de publicação do artigo 11/2025), ou seja, os mantenedores não garantem um funcionamento 100% confiável em ambientes produtivos. Todavia o projeto se mostra muito promissor e logo logo (assim esperamos) estará production ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/kedacore/http-add-on" rel="noopener noreferrer"&gt;https://github.com/kedacore/http-add-on&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kedacore.github.io/http-add-on" rel="noopener noreferrer"&gt;https://kedacore.github.io/http-add-on&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://keda.sh/docs/2.18" rel="noopener noreferrer"&gt;https://keda.sh/docs/2.18&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://minikube.sigs.k8s.io/docs" rel="noopener noreferrer"&gt;https://minikube.sigs.k8s.io/docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>performance</category>
      <category>kubernetes</category>
      <category>microservices</category>
      <category>devops</category>
    </item>
    <item>
      <title>Gerando embeddings com PHP e ONNX</title>
      <dc:creator>jonas-elias</dc:creator>
      <pubDate>Mon, 15 Jul 2024 21:13:56 +0000</pubDate>
      <link>https://dev.to/jonas-elias/gerando-embeddings-com-php-e-onnx-44gk</link>
      <guid>https://dev.to/jonas-elias/gerando-embeddings-com-php-e-onnx-44gk</guid>
      <description>&lt;h1&gt;
  
  
  IA e PHP
&lt;/h1&gt;

&lt;p&gt;No campo da inteligência artificial (IA) e processamento de linguagem natural (NLP), &lt;em&gt;embeddings&lt;/em&gt; são representações matemáticas de palavras, frases ou documentos que capturam seu significado semântico. Esses &lt;em&gt;embeddings&lt;/em&gt; são utilizados para aplicações que incluem busca semântica, análise de sentimentos, entre outros. A criação de &lt;em&gt;embeddings&lt;/em&gt; geralmente envolve técnicas de aprendizado de máquina que tradicionalmente são implementadas em linguagens como Python. No entanto, com a crescente popularidade da arquitetura &lt;a href="https://github.com/onnx/onnx" rel="noopener noreferrer"&gt;Open Neural Network Exchange&lt;/a&gt; (ONNX), é possível integrar modelos pré-treinados em diferentes linguagens de programação, incluindo PHP.&lt;/p&gt;

&lt;h1&gt;
  
  
  Transformers PHP
&lt;/h1&gt;

&lt;p&gt;Para utilização dos modelos de inteligência artificial visando a geração de &lt;em&gt;embeddings&lt;/em&gt; no PHP, é possível utilizar a biblioteca &lt;a href="https://github.com/CodeWithKyrian/transformers-php" rel="noopener noreferrer"&gt;TransformersPHP&lt;/a&gt;, no qual foi projetada para ser funcionalmente equivalente à biblioteca &lt;a href="https://pypi.org/project/transformers/" rel="noopener noreferrer"&gt;Transformers&lt;/a&gt; em Python, mantendo o mesmo nível de desempenho e facilidade de uso. O TransformersPHP utiliza o ONNX Runtime para executar os modelos pré-treinados.&lt;/p&gt;

&lt;h1&gt;
  
  
  Arquitetura Exemplo
&lt;/h1&gt;

&lt;p&gt;A seguir, é possível observar visualmente o funcionamento da geração de embeddings a partir da biblioteca TransformersPHP:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq0cwdz4iv9mhsj62k2jc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq0cwdz4iv9mhsj62k2jc.png" alt="Image description" width="800" height="318"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Uso
&lt;/h1&gt;

&lt;p&gt;Primeiramente, realize a configuração da imagem que será utilizada pelo container. Para utilização do TransformersPHP com suporte a geração de &lt;em&gt;embeddings&lt;/em&gt;, é necessário o uso das extensões &lt;code&gt;FFI&lt;/code&gt; e &lt;code&gt;Imagick&lt;/code&gt;. A extensão &lt;code&gt;FFI&lt;/code&gt;  é a interface de integração entre código binário e a linguagem PHP. Já o &lt;code&gt;Imagick&lt;/code&gt; é utilizado para o processamento dos modelos pré-treinados.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; php:8.3&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; libffi-dev &lt;span class="se"&gt;\
&lt;/span&gt;        git &lt;span class="se"&gt;\
&lt;/span&gt;        unzip &lt;span class="se"&gt;\
&lt;/span&gt;        libmagickwand-dev &lt;span class="se"&gt;\
&lt;/span&gt;        libmagickcore-dev      

&lt;span class="k"&gt;RUN &lt;/span&gt;docker-php-ext-configure ffi &lt;span class="nt"&gt;--with-ffi&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-php-ext-install ffi

&lt;span class="k"&gt;RUN &lt;/span&gt;pecl &lt;span class="nb"&gt;install &lt;/span&gt;imagick &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-php-ext-enable imagick

&lt;span class="k"&gt;RUN &lt;/span&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; https://getcomposer.org/installer | php &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--install-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/bin &lt;span class="nt"&gt;--filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;composer

&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /embeddings

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /embeddings&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["/bin/bash"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após isso, é possível realizar a criação da imagem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t image-php-ffi .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Seguida da execução do container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -it --rm --name container-php-ffi image-php-ffi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dentro do container, é necessário primeiramente adicionar a dependência &lt;code&gt;codewithkyrian/transformers&lt;/code&gt;, logo deve-se executar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require codewithkyrian/transformers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso, o ambiente está configurado e pronto para receber o código que fará a geração do embedding. Abaixo, é possível verificar que o código PHP faz referência ao modelo &lt;code&gt;Xenova/bert-base-uncased&lt;/code&gt;, disponibilizado pela iniciativa &lt;a href="https://huggingface.co/Xenova" rel="noopener noreferrer"&gt;Xenova&lt;/a&gt;, no qual oferece modelos pré-treinados a partir da arquitetura ONNX.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;require_once&lt;/span&gt; &lt;span class="s1"&gt;'./vendor/autoload.php'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Codewithkyrian\Transformers\Transformers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;Codewithkyrian\Transformers\Pipelines\pipeline&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nn"&gt;Codewithkyrian\Transformers\Utils\&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;memoryUsage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeUsage&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nc"&gt;Transformers&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$extractor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'feature-extraction'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Xenova/bert-base-uncased'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$extractor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'The quick brown fox jumps over the lazy dog.'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;normalize&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pooling&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'mean'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nb"&gt;var_dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$embeddings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nf"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;memoryUsage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;timeUsage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;milliseconds&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$embeddings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Realize a criação de um novo arquivo PHP, copie o código acima e após isso, execute o arquivo com &lt;code&gt;php nome_arquivo.php&lt;/code&gt;. A primeira execução pode requerer um tempo de processamento maior por conta do &lt;em&gt;download&lt;/em&gt; do modelo pré-treinado.&lt;/p&gt;

&lt;h1&gt;
  
  
  Busca Semântica
&lt;/h1&gt;

&lt;p&gt;A geração de &lt;em&gt;embeddings&lt;/em&gt; pode ser benéfica para produzir sistemas de busca ao nível semântico, como abordo mais especificamente na palestra &lt;a href="https://www.youtube.com/watch?v=fpQDvcj5Fb4" rel="noopener noreferrer"&gt;Palestra APIs e LLMs&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Desvantagens
&lt;/h1&gt;

&lt;p&gt;Utilizar PHP e a arquitetura ONNX para gerar &lt;em&gt;embeddings&lt;/em&gt; pode apresentar algumas desvantagens. A maioria dos modelos &lt;em&gt;transformers&lt;/em&gt; são desenvolvidos com a arquitetura &lt;code&gt;PyTorch&lt;/code&gt;, que é fortemente integrada à linguagem Python, limitando a realização de testes e desenvolvimento em outras linguagens. A conversão de modelos &lt;code&gt;PyTorch&lt;/code&gt; para ONNX pode ser complexa ou até inviável, dependendo do suporte e das atualizações fornecidas pelos mantenedores dos modelos.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusão
&lt;/h1&gt;

&lt;p&gt;Integrar IA e NLP com PHP utilizando a arquitetura ONNX é uma abordagem promissora que permite a utilização de modelos pré-treinados em uma linguagem de programação amplamente usada no desenvolvimento web. A biblioteca TransformersPHP demonstra ser uma ferramenta funcionalmente equivalente à sua contraparte em Python, permitindo a geração de embeddings com facilidade e eficiência.&lt;/p&gt;

&lt;p&gt;Embora existam desafios, como a complexidade na conversão de modelos e a necessidade de extensões específicas, a utilização de PHP para geração de embeddings pode abrir novas oportunidades para desenvolvedores web que desejam incorporar capacidades de NLP em suas aplicações sem a necessidade de migrar para outras linguagens.&lt;/p&gt;

&lt;p&gt;Com a evolução contínua dessas tecnologias e o aumento do suporte da comunidade, espera-se que as barreiras atuais sejam progressivamente reduzidas, tornando essa abordagem cada vez mais acessível e eficaz para diversos desenvolvedores e aplicações.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/onnx/onnx" rel="noopener noreferrer"&gt;ONNX&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/CodeWithKyrian/transformers-php" rel="noopener noreferrer"&gt;Transformers PHP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codewithkyrian.github.io/transformers-php/" rel="noopener noreferrer"&gt;Transformers PHP - DOC&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pypi.org/project/transformers/" rel="noopener noreferrer"&gt;Transformers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/docs/transformers/index" rel="noopener noreferrer"&gt;Transformers Hugging Face&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hub.docker.com/_/php" rel="noopener noreferrer"&gt;Docker PHP&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://huggingface.co/Xenova" rel="noopener noreferrer"&gt;Xenova&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Substituindo o Redis pelo Valkey em projetos PHP/Hyperf</title>
      <dc:creator>jonas-elias</dc:creator>
      <pubDate>Tue, 21 May 2024 02:12:25 +0000</pubDate>
      <link>https://dev.to/jonas-elias/substituindo-o-redis-pelo-valkey-em-projetos-phphyperf-3lh0</link>
      <guid>https://dev.to/jonas-elias/substituindo-o-redis-pelo-valkey-em-projetos-phphyperf-3lh0</guid>
      <description>&lt;h2&gt;
  
  
  Licença Redis
&lt;/h2&gt;

&lt;p&gt;Recentemente, o Redis estava disponível sob a &lt;strong&gt;Licença Pública Geral Affero&lt;/strong&gt; (AGPL), uma licença de código aberto que exigia que qualquer software modificado usando o Redis também fosse distribuído sob os termos da AGPL. Isso significava que qualquer empresa que construísse um produto sobre o Redis e o modificasse de alguma forma tinha a obrigação de compartilhar essas modificações com a comunidade.&lt;/p&gt;

&lt;p&gt;O novo modelo de licenciamento do Redis baseia-se em duas novas licenças: a &lt;strong&gt;Redis Source Available License&lt;/strong&gt; (RSAL) e a &lt;strong&gt;Redis Commons Clause&lt;/strong&gt;. A RSAL permite o acesso ao código-fonte do Redis, mas com restrições sobre sua utilização. Já a &lt;strong&gt;Redis Commons Clause&lt;/strong&gt;, uma adição à RSAL, impõe restrições adicionais, proibindo o uso comercial do software em determinados contextos, a menos que uma licença comercial seja adquirida.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternativas
&lt;/h2&gt;

&lt;p&gt;Existem alternativas como Memcached, DynamoDB, entre outros. Todos estes mencionados podem gerar reescrita de código, dependendo do formato no qual o projeto foi escrito. Para evitar os problemas mencionados anteriormente, apresento o &lt;a href="https://github.com/valkey-io/valkey" rel="noopener noreferrer"&gt;Valkey&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;O Valkey trata-se basicamente de um fork do Redis, logo, a lógica de implementação continua a mesma. O "pulo do gato" está em relação ao tipo de licença, que permite a comercialização por estar ligada a &lt;code&gt;Copyright (c) 2024-present, Valkey contributors&lt;/code&gt; e &lt;code&gt;Copyright (c) 2006-2020, Salvatore Sanfilippo&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementação
&lt;/h2&gt;

&lt;p&gt;Mas e agora? Como proceder em meu projeto PHP?&lt;/p&gt;

&lt;p&gt;Irei apresentar um exemplo utilizando o framework Hyperf, mas nada impede a implementação também no Laravel, Symfony, ou qualquer outro framework que utiliza conectores Redis.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;docker-compose.yml&lt;/code&gt; abaixo realiza o pull da imagem &lt;code&gt;valkey/valkey&lt;/code&gt;, possibilitando o uso no container de uma aplicação &lt;code&gt;Hyperf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3"&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis-to-valkey&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hyperf-valkey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hyperf-valkey&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;9501:9501&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;valkey&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;

  &lt;span class="na"&gt;valkey&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;valkey&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;valkey/valkey&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;6379:6379&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O backend &lt;code&gt;hyperf-valkey&lt;/code&gt; é construído com base no Dockerfile abaixo (instalando também a extensão interface &lt;a href="https://pecl.php.net/package/redis" rel="noopener noreferrer"&gt;redis-php&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; php:8.2&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-install-recommends&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    wget &lt;span class="se"&gt;\
&lt;/span&gt;    vim &lt;span class="se"&gt;\
&lt;/span&gt;    git &lt;span class="se"&gt;\
&lt;/span&gt;    unzip

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-install-recommends&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    libzip-dev &lt;span class="se"&gt;\
&lt;/span&gt;    libcurl4-openssl-dev &lt;span class="se"&gt;\
&lt;/span&gt;    libssl-dev &lt;span class="se"&gt;\
&lt;/span&gt;    libpq-dev &lt;span class="se"&gt;\
&lt;/span&gt;    libjpeg-dev &lt;span class="se"&gt;\
&lt;/span&gt;    libpng-dev &lt;span class="se"&gt;\
&lt;/span&gt;    libfreetype6-dev &lt;span class="se"&gt;\
&lt;/span&gt;    g++ &lt;span class="se"&gt;\
&lt;/span&gt;    libaio-dev &lt;span class="se"&gt;\
&lt;/span&gt;    libicu-dev

&lt;span class="k"&gt;RUN &lt;/span&gt;curl &lt;span class="nt"&gt;-sS&lt;/span&gt; https://getcomposer.org/installer | php &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nt"&gt;--install-dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/local/bin &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nt"&gt;--filename&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;composer

&lt;span class="k"&gt;RUN &lt;/span&gt;docker-php-ext-configure gd &lt;span class="nt"&gt;--with-freetype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/include/ &lt;span class="nt"&gt;--with-jpeg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/usr/include/ &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pecl &lt;span class="nb"&gt;install &lt;/span&gt;redis &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s2"&gt;"no&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;yes&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;no&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;yes&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | pecl &lt;span class="nb"&gt;install &lt;/span&gt;swoole &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"swoole.use_shortname = Off"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /usr/local/etc/php/conf.d/swoole.ini &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-php-ext-install &lt;span class="se"&gt;\
&lt;/span&gt;    pcntl &lt;span class="se"&gt;\
&lt;/span&gt;    gd &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; docker-php-ext-enable &lt;span class="se"&gt;\
&lt;/span&gt;    redis &lt;span class="se"&gt;\
&lt;/span&gt;    swoole

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 9501&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após isso, acesse o container via &lt;code&gt;bash&lt;/code&gt; ou &lt;code&gt;remote containers&lt;/code&gt; e crie o projeto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer create-project hyperf/hyperf-skeleton
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No questionamento &lt;code&gt;Do you want to use Redis Client?&lt;/code&gt;, selecione &lt;code&gt;y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04e0fa79runboedjez1p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F04e0fa79runboedjez1p.png" alt="Do you want to use Redis Client?" width="523" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No arquivo &lt;code&gt;.env&lt;/code&gt;, altere as chaves REDIS para:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REDIS_HOST=valkey
REDIS_AUTH=(null)
REDIS_PORT=6379
REDIS_DB=0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso, a conexão Valkey com o projeto Hyperf já está concluída. Para utilizar a funcionalidade de cache com o Valkey, vamos acessar a &lt;code&gt;IndexController.php&lt;/code&gt; e substituir o conteúdo existente pelo código abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="k"&gt;declare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strict_types&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Hyperf\Redis\Redis&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nc"&gt;Valkey&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IndexController&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractController&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;Valkey&lt;/span&gt; &lt;span class="nv"&gt;$valkey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'hello valkey!'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'cache'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;valkey&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$content&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;valkey&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$key&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inicie a aplicação com &lt;code&gt;php bin/hyperf.php start&lt;/code&gt;, acessando posteriormente o endereço &lt;a href="http://127.0.0.1:9501" rel="noopener noreferrer"&gt;http://127.0.0.1:9501&lt;/a&gt;, tendo como retorno:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqkjb6m0xmevhr0rc9mzl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqkjb6m0xmevhr0rc9mzl.png" alt="Hello Valkey" width="435" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerações
&lt;/h2&gt;

&lt;p&gt;Para projetos em andamento que já estão utilizando o Redis, basta substituir o host Redis pelo serviço Valkey (via container, como exemplificado). Além disso, projetos Laravel podem seguir a mesma lógica utilizando a biblioteca &lt;code&gt;predis/predis&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O ideal pela questão de nomenclaturas e responsabilidades, seria utilizar/criar pacotes específicos para o Valkey, já que provavelmente receberá modificações específicas ao longo do tempo, distanciando um pouco a equivalência com o projeto Redis. Contudo, a solução apresentada neste artigo é viável.&lt;/p&gt;

&lt;h3&gt;
  
  
  Referências
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://redis.io/legal/licenses" rel="noopener noreferrer"&gt;Redis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@darioajr/o-novo-licenciamento-do-redis-e-seu-impacto-no-mercado-81c1ae11e1cd" rel="noopener noreferrer"&gt;Licenças&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hyperf.wiki/3.1/#/en" rel="noopener noreferrer"&gt;Hyperf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hyperf/hyperf-docker" rel="noopener noreferrer"&gt;Docker Hyperf&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/valkey-io/valkey" rel="noopener noreferrer"&gt;Valkey&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hub.docker.com/r/valkey/valkey" rel="noopener noreferrer"&gt;Docker Valkey&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>redis</category>
      <category>valkey</category>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>VueJS + Tailwind + DaisyUI = 😎🌷</title>
      <dc:creator>jonas-elias</dc:creator>
      <pubDate>Mon, 20 May 2024 18:36:23 +0000</pubDate>
      <link>https://dev.to/jonas-elias/vuejs-tailwind-daisyui--1356</link>
      <guid>https://dev.to/jonas-elias/vuejs-tailwind-daisyui--1356</guid>
      <description>&lt;p&gt;Vue é um robusto framework JavaScript dedicado à construção de interfaces de usuário interativas e dinâmicas. Esta ferramenta poderosa é construída sobre os fundamentos da web moderna: HTML, CSS e JavaScript. Com um modelo de programação declarativo e baseado em componentes, o Vue capacita os desenvolvedores a criar interfaces de usuário de qualquer complexidade de forma eficiente e organizada.&lt;/p&gt;

&lt;p&gt;Além disso, abrange a maioria dos recursos comuns necessários no desenvolvimento de frontend. No entanto, a web é extremamente diversa - as coisas que construímos na web podem variar drasticamente em forma e escala. Com isso em mente, Vue é projetado para ser flexível e adotável incrementalmente. Dependendo do seu caso de uso, Vue pode ser utilizado de diferentes maneiras:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Aprimorando HTML estático sem um passo de compilação&lt;/li&gt;
&lt;li&gt;Incorporando como Componentes da Web em qualquer página
Aplicação de Página Única (SPA)&lt;/li&gt;
&lt;li&gt;Fullstack / Renderização do Lado do Servidor (SSR)&lt;/li&gt;
&lt;li&gt;Jamstack / Geração de Site Estático (SSG)&lt;/li&gt;
&lt;li&gt;Direcionamento para desktop, mobile, WebGL e até mesmo o terminal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para criar um novo projeto Vue, certifique-se de ter uma versão atualizada do Node.js instalada e que seu diretório de trabalho atual seja o onde pretende criar um projeto. Execute o seguinte comando em sua linha de comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;npm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✔ Project name: … &amp;lt;your-project-name&amp;gt;
✔ Add TypeScript? … No
✔ Add JSX Support? … No
✔ Add Vue Router for Single Page Application development? … No
✔ Add Pinia for state management? … No
✔ Add Vitest for Unit testing? … No
✔ Add an End-to-End Testing Solution? … No
✔ Add ESLint for code quality? … Yes
✔ Add Prettier for code formatting? … No
✔ Add Vue DevTools 7 extension for debugging? (experimental) … No

Scaffolding project in ./&amp;lt;your-project-name&amp;gt;...
Done.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;your-project-name&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;npm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;npm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;dev&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso você já possui um projeto Vue sendo executado localmente.&lt;/p&gt;

&lt;p&gt;O projeto pode ser integrado com Tailwind CSS, sendo &lt;br&gt;
um framework CSS orientado para utilitários, repleto de classes como flex, pt-4, text-center e rotate-90, que podem ser combinadas para construir qualquer design diretamente em seu markup.&lt;/p&gt;

&lt;p&gt;Para instalá-lo em seu projeto, basta executar a instalação das dependências abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;npm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-D&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tailwindcss&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;postcss&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;autoprefixer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;npx&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tailwindcss&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-p&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure o arquivo &lt;code&gt;tailwind.config.js&lt;/code&gt; adicionando em seu content as diretivas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/**/*.{vue,js,ts,jsx,tsx}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,],&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adicione as diretivas do tailwind no arquivo CSS carregado no componente central (ou carrego-o manualmente com as diretivas abaixo):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para finalizar a configuração do projeto, vamos adicionar o plugin daisyUI - Tailwind CSS. O daisyUI adiciona nomes de classes de componentes ao Tailwind CSS para que você possa criar websites bonitos mais rapidamente.&lt;/p&gt;

&lt;p&gt;Para adicioná-lo ao projeto, basta executar os comandos abaixo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;npm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-D&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;daisyui&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;latest&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E configurá-lo no arquivo &lt;code&gt;tailwind.config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/**/*.{vue,js,ts,jsx,tsx}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,],&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;daisyui&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),],&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com esses passos, seu projeto Vue estará pronto para criar interfaces de usuário dinâmicas e esteticamente agradáveis de forma eficiente. A combinação do Vue com o Tailwind CSS e o daisyUI oferece uma experiência de desenvolvimento ágil e flexível, permitindo que você se concentre na criação de ótimas experiências para os usuários finais.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://vuejs.org" rel="noopener noreferrer"&gt;https://vuejs.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tailwindcss.tw" rel="noopener noreferrer"&gt;https://tailwindcss.tw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://daisyui.com" rel="noopener noreferrer"&gt;https://daisyui.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
