Como implantar um aplicativo Rust?
O Rust tem sido a linguagem mais admirada na pesquisa de desenvolvedores do StackOverflow há mais de quatro anos, devido aos vários recursos que oferece aos usuários.
A Mozilla criou o Rust para ser confiável, eficiente e amigável ao desenvolvedor. O Rust tem uma sintaxe semelhante à de linguagens como C++ e C, cujos desenvolvedores são o principal alvo da linguagem.
O Rust também se concentra na segurança da memória e na concorrência com modelos que evitam as armadilhas associadas que os desenvolvedores que usam outras linguagens enfrentam.
Você aprenderá a criar APIs em Rust para aproveitar os benefícios deste artigo. Você aprenderá a criar, conteinerizar e implantar um aplicativo Rust no serviço de conteinerização gratuito do Back4app.
Contents
- 0.1 Vantagens de usar o Rust
- 0.2 Limitações do uso do Rust
- 0.3 Opções de implantação do Rust
- 0.4 O processo de implantação do aplicativo Rust
- 1 O que é o Back4app?
- 1.1 Criação e implementação
- 1.2 A função do manipulador de POST
- 1.3 A função do manipulador GET
- 1.4 A função PUT Handler
- 1.5 A função do manipulador DELETE
- 1.6 Mapeamento das funções do manipulador para rotas
- 1.7 Armazenamento em contêiner de aplicativos Rust com o Docker
- 1.8 Implantação de um contêiner no Back4app
- 1.9 Implementação com o Back4app AI Agent
- 1.10 Conclusão
Vantagens de usar o Rust
Há muitas vantagens em usar o Rust em seus projetos. Aqui estão algumas das mais importantes:
Abstrações de custo zero
O Rust fornece abstrações de alto nível sem impor custos adicionais de tempo de execução. Isso insinua que as abstrações que você usa em seu código (funções, iteradores ou genéricos) não tornam seus programas mais lentos.
O compilador do Rust otimiza manualmente as abstrações do código de baixo nível compilado. O Rust preenche a lacuna entre o controle expressivo, de baixo nível e refinado sobre o desempenho.
A abordagem Fearless Concurrency para segurança de memória em programas simultâneos
O Rust adota uma “abordagem destemida” para a concorrência, caracterizada pela segurança e eficiência. O modelo de simultaneidade do Rust aproveita seu modelo de propriedade e a verificação de tipos para evitar corridas de dados em tempo de compilação.
Esse recurso permite que você crie aplicativos com vários threads sem as desvantagens da simultaneidade de estado compartilhado, como deadlocks e condições de corrida.
Sistema avançado de tipos e modelo de propriedade
O sistema de tipos do Rust e suas regras de propriedade são recursos exclusivos que ajudam a reforçar a segurança da memória.
O modelo de propriedade usa o verificador de empréstimos para garantir que cada parte dos dados tenha um único proprietário e gerencia seu ciclo de vida para evitar problemas como ponteiros oscilantes e vazamentos de memória.
Compatibilidade e integração entre plataformas
O Rust é uma ótima opção se você deseja criar aplicativos multiplataforma. Você pode escrever o código uma vez e compilá-lo em várias plataformas sem alterações significativas na base de código existente.
O Rust se integra bem a outras linguagens de programação, especialmente C, o que torna a linguagem adequada para montagem na Web e tarefas de sistemas incorporados.
Limitações do uso do Rust
É provável que você encontre alguns contratempos ao criar aplicativos de nível de produção com o Rust.
Algumas delas podem incluir a curva de aprendizado acentuada do Rust, o tempo de compilação mais longo devido à memória e a outras verificações, e seu novo e pequeno ecossistema.
Há algumas desvantagens que você pode encontrar ao criar produtos de nível de produção com o Rust. Aqui estão alguns deles:
A curva de aprendizado da programação em Rust é acentuada
Em comparação com outras linguagens populares (Go, Python, JavaScript etc.), é necessário um tempo significativo para dominar o Rust e criar aplicativos de nível de produção com essa linguagem.
Isso não deve fazer com que você deixe de usar o Rust. Ao dominar o Rust, você se tornará realmente produtivo na criação e implantação de aplicativos, além de obter todos os benefícios do uso do Rust.
Os programas Rust têm um longo tempo de compilação
As verificações de memória e simultaneidade no momento da compilação, juntamente com vários outros fatores, resultam em longos tempos de compilação para os programas Rust.
Dependendo do tamanho do aplicativo, longos tempos de compilação podem resultar em gargalos nos estágios de desenvolvimento ou produção.
O Rust tem um ecossistema menor de bibliotecas
O Rust é relativamente novo em comparação com muitas outras linguagens populares, e há um ecossistema limitado de bibliotecas que você pode usar.
Muitas bibliotecas (crates) ainda estão em produção, e você pode consultar sites como AreWeWebYet para obter uma visão geral das crates prontas para produção que podem ser usadas para criar aplicativos Web em Rust.
Opções de implantação do Rust
O Rust já está sendo amplamente adotado, portanto, há muitas opções de implantação que você pode escolher para seus aplicativos.
A maioria das opções de implementação do Rust são plataformas baseadas em IaaS ou CaaS. Você pode escolher uma delas com base nas especificações do seu projeto.
Infraestrutura como serviço (IaaS), como o AWS
Os provedores de infraestrutura como serviço (IaaS) fornecem a infraestrutura para implementar e gerenciar seus aplicativos executados em máquinas virtuais na nuvem.
Você pode usar os serviços que as plataformas IaaS fornecem para implantar seus aplicativos Rust em máquinas virtuais que executam sistemas operacionais como Linux, Windows, macOS e outros sistemas operacionais compatíveis com o Rust.
Aqui está uma lista das plataformas populares de IaaS:
- Amazon Web Services
- Digital Ocean
- Google Cloud
- Linode
- Microsoft Azure
Containerização como serviço, como o Back4app Containers
Os provedores de serviços de conteinerização (CaaS) ajudam a facilitar a implantação do seu aplicativo com tecnologias de conteinerização.
Para implantar seu aplicativo em plataformas que suportam a conteinerização, você agrupará seu aplicativo e todas as suas dependências em um contêiner isolado.
Os contêineres são isolados e portáteis, mas você terá que trabalhar dentro dos limites dos recursos do provedor de CaaS.
Alguns provedores de IaaS oferecem funções de CaaS. Além disso, há plataformas que oferecem apenas a funcionalidade flexível de CaaS isoladamente.
Aqui está uma lista de algumas plataformas de CaaS:
- Oracle Container Service
- Back4app
- Mirantix
- Docker Enterprise
O processo de implantação do aplicativo Rust
Nesta seção, você aprenderá como implantar seu aplicativo Rust na plataforma CaaS do Back4app.
O que é o Back4app?
O Back4app é uma plataforma em nuvem que você pode utilizar para criar e implantar todos os tipos de serviços de back-end para seus aplicativos móveis, da Web e outros tipos.
O Back4app fornece um agente de IA que você pode usar para simplificar a implantação do seu aplicativo na plataforma. Você pode usá-lo para gerenciar seus repositórios do GitHub, implantar código na nuvem com facilidade e gerenciar seus aplicativos em execução.
Nos servidores de back-end da Back4app, os contêineres personalizados podem ser implantados e executados por meio da funcionalidade CaaS.
Usando as imagens do contêiner, você pode estender a lógica do aplicativo sem se preocupar com a manutenção da arquitetura do servidor.
Criação e implementação
Você deve ter o Rust instalado em seu computador para seguir este tutorial. Você pode visitar a página de instalações do Rust para conhecer as diferentes opções de instalação disponíveis.
Depois de instalar o Rust, crie uma sessão de terminal e execute este comando para inicializar um novo projeto Rust
mkdir back4app-rust-deployment && cd back4app-rust-deployment && cargo init
Ao executar o comando, você deverá ver um arquivo cargo.toml
no novo diretório que acabou de criar. Você usará o cargo.toml
para gerenciar as dependências.
Em seguida, adicione essas diretivas à seção [dependencies]
do seu arquivo Cargo.toml
para instalar essas dependências ao compilar o aplicativo.
[dependencies]
actix-web = "4.0"
serde = { version = "1.0", features = ["derive"] }
serde_derive = { version = "1.0" }
serde_json = "1.0"
lazy_static = "1.4"
A base actix-web
fornece roteamento e outras funções relacionadas a HTTP, as bases serde
, serde_derive
e serde_json
fornecem funções para as diferentes operações JSON e a base lazy_static
fornece o armazenamento de dados na memória para a API em tempo de execução.
Adicione essas importações na parte superior de seu arquivo [main.rs](<http://main
.rs>):
use serde::{Serialize, Deserialize};
use actix_web::{web, App, HttpServer, HttpResponse, Error};
use std::sync::Mutex;
extern crate lazy_static;
use lazy_static::lazy_static;
Você pode usar um struct para definir a estrutura de dados da sua API com base nos campos necessários. Esta é uma estrutura que mostra uma pessoa com um ID, nome de usuário e e-mail.
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Person {
pub id: i32,
pub username: String,
pub email: String,
}
Os #[derive(Serialize, Deserialize, Debug, Clone)]
são implementações da caixa serde_derive
para que a estrutura Person
acesse e use suas funções.
Veja como você pode usar o crate lazy_static
para configurar um armazenamento de dados na memória para sua API com base no tipo de estrutura Person
:
lazy_static! {
static ref DATA_STORE: Mutex<Vec<Person>> = Mutex::new(Vec::new());
}
Você criou um armazenamento compartilhado, inicializado de forma preguiçosa e thread-safe para a estrutura People. Você o usará em suas funções de manipulador para armazenar e recuperar dados.
A função do manipulador de POST
A função de manipulador de solicitação POST aceita uma representação JSON da estrutura Person
como entrada. Em seguida, ela retornará uma resposta HTTP e um erro para o cliente na solicitação.
Adicione este bloco de código ao seu arquivo [main.rs]()
para implementar a funcionalidade do manipulador de solicitações POST.
async fn create_person(new_person: web::Json<Person>) -> Result<HttpResponse, Error> {
let mut data_store = DATA_STORE.lock().unwrap();
let new_id = data_store.len() as i32 + 1;
let mut person = new_person.into_inner();
person.id = new_id;
data_store.push(person.clone());
Ok(HttpResponse::Ok().json(person))
}
A função create_person
é uma função assíncrona que acessa o armazenamento de dados compartilhados, gera um novo ID para a estrutura Person
, converte a representação JSON Person
em uma estrutura e a envia para o armazenamento de dados.
Após uma solicitação bem-sucedida, a função fornece ao cliente os dados que foram inseridos no banco de dados juntamente com um código de status 200.
A função do manipulador GET
Aqui, uma função de manipulador GET demonstra a leitura de todos os dados no armazenamento de dados e os retorna ao cliente como JSON.
Adicione este bloco de código ao seu projeto para implementar uma função de manipulador de GET
async fn get_people() -> Result<HttpResponse, Error> {
let data_store = DATA_STORE.lock().unwrap();
let people: Vec<Person> = data_store.clone();
Ok(HttpResponse::Ok().json(people))
}
A função get_people
é uma função assíncrona que acessa o armazenamento de dados e grava o conteúdo no cliente como uma resposta.
Em uma solicitação bem-sucedida, a função responde com o código de status 200
para o cliente com todos os dados no armazenamento de dados.
A função PUT Handler
Sua função de manipulador de solicitação PUT deve atualizar uma entrada no armazenamento de dados com base em um campo do objeto.
Veja como você pode implementar uma função de manipulador de PUT para sua API:
async fn update_person(
id: web::Path<i32>,
person_update: web::Json<Person>,
) -> Result<HttpResponse, Error> {
let mut data_store = DATA_STORE.lock().unwrap();
if let Some(person) = data_store.iter_mut().find(|p| p.id == *id) {
*person = person_update.into_inner();
Ok(HttpResponse::Ok().json("Person updated successfully"))
} else {
Ok(HttpResponse::NotFound().json("Person not found"))
}
}
A função update_person
recebe o ID e a nova entrada da solicitação. Em seguida, ela percorre o armazenamento de dados e substitui a entrada pela nova, se ela existir.
A função do manipulador DELETE
A função de solicitação DELETE receberá um argumento: o campo ID da solicitação feita. Na execução da função, ela excluirá a entrada com a ID do armazenamento de dados.
Adicione essa implementação da função de manipulador DELETE ao seu programa.
// DELETE
pub async fn delete_person(id: web::Path<i32>) -> Result<HttpResponse, Error> {
let mut data_store = DATA_STORE.lock().unwrap();
if let Some(index) = data_store.iter().position(|p| p.id == *id) {
data_store.remove(index);
Ok(HttpResponse::Ok().json("Deleted successfully"))
} else {
Ok(HttpResponse::NotFound().json("Person not found"))
}
}
A função delete_person
exclui do armazenamento de dados a entrada com o ID especificado. Dependendo do estado da operação, a função retorna ao cliente uma cadeia de caracteres e um código de status.
Mapeamento das funções do manipulador para rotas
Depois de definir os pontos de extremidade, você precisará mapear as rotas para as funções do manipulador para acessar a funcionalidade das funções do manipulador.
Veja como você pode atribuir rotas a funções de manipulador:
#[actix_web::main]
async fn main() -> std::io::Result<()> {
HttpServer::new(|| {
App::new()
.route("/person", web::post().to(create_person))
.route("/people", web::get().to(get_people))
.route("/person/{id}", web::put().to(update_person))
.route("/person/{id}", web::delete().to(delete_person))
})
.bind("0.0.0.0:8000")?
.run()
.await
}
A função principal
é uma função assíncrona que configura o servidor depois de mapear as rotas para as funções do manipulador.
A função HttpServer::new
instancia um servidor HTTP, a função App::new()
cria uma nova instância de aplicativo e a função route
mapeia rotas para a função handler.
A função bind
especifica o endereço do novo aplicativo, e a função run
executa o aplicativo.
Armazenamento em contêiner de aplicativos Rust com o Docker
O Docker é a tecnologia de conteinerização mais popular do mercado. Você pode conteinerizar seus aplicativos Rust com o Docker para portabilidade e implantá-los no Back4app com apenas alguns cliques.
Execute este comando para criar um novo Dockerfile em seu projeto:
touch Dockerfile
Abra o Dockerfile e adicione essas instruções de compilação ao Dockerfile:
# Use Rust Nightly as the base image
FROM rustlang/rust:nightly
# Set the working directory inside the container
WORKDIR /usr/src/myapp
# Copy the current directory contents into the container
COPY . .
# Build the application
RUN cargo build --release
# Expose port 8000
EXPOSE 8000
# Define the command to run the application
CMD ["./target/release/back4app-rust-deployment"]
Essas instruções especificam a imagem de base e as instruções de compilação para colocar seu aplicativo Rust em contêineres com o Docker.
Aqui está um detalhamento do conteúdo do Dockerfile:
- A diretiva
FROM rustlang/rust:nightly
especifica a imagem base para o Dockerfile. O Docker extrai essa imagem do repositório e constrói seus programas nela. - A diretiva
WORKDIR /usr/src/myapp
define o diretório de trabalho do seu aplicativo dentro do contêiner. - A diretiva
COPY . .
copia todo o conteúdo do seu diretório de trabalho para o diretório de trabalho atual do contêiner. - A diretiva
RUN cargo build --release
executa o comando para criar seu aplicativo no contêiner. - A diretiva
EXPOSE 8000
expõe a porta8000
do contêiner para solicitações de entrada. - O
CMD ["./target/release/back4app-rust-deployment"]
executa o programa (o executável da operação de compilação).
Depois de escrever o Dockerfile, você pode prosseguir com a implantação do contêiner no serviço de contêineres do Back4app.
Implantação de um contêiner no Back4app
É necessário criar uma conta no Back4app para implementar contêineres.
Veja a seguir as etapas para criar uma conta no Back4app.
- Visite o site da Back4app
- Clique no botão Registrar-se no canto superior direito da página.
- Preencha o formulário de registro e envie-o para criar a conta.
Agora que você criou uma conta Back4app com sucesso, faça login e clique no botão NOVO APP
localizado no canto superior direito da página inicial.
Você verá opções para escolher como deseja criar seu aplicativo. Escolha a opção Container as a Service (Contêiner como serviço
).
Agora, conecte sua conta do Github à sua conta do Back4app e configure o acesso aos repositórios em sua conta ou em um projeto específico.
Escolha o aplicativo que você deseja implantar (o deste tutorial) e clique em selecionar.
Ao clicar em selecionar, o botão o levará a uma página na qual você poderá preencher informações sobre o aplicativo, incluindo o nome da ramificação, o diretório raiz e as variáveis de ambiente.
O processo de implantação é iniciado automaticamente,
Implementação com o Back4app AI Agent
Para turbinar seu fluxo de trabalho de desenvolvimento, você também pode implantar seu aplicativo usando o agente de IA do Back4app, como você pode ver na imagem abaixo:
Siga este link para instalar o aplicativo contêiner Back4app na sua conta do GitHub e siga as etapas da imagem acima para configurá-lo.
Ao concluir a configuração do aplicativo, você pode prosseguir com a implantação do aplicativo com o agente de IA.
Siga o link fornecido para monitorar o progresso da implantação do seu aplicativo.
Conclusão
Você aprendeu a criar e implantar um aplicativo Rust em contêineres do Docker no Back4app.
A implantação de seus aplicativos no Back4app é uma ótima maneira de simplificar o gerenciamento da infraestrutura de back-end.
O Back4App oferece ferramentas avançadas para gerenciar seus dados, dimensionar seu aplicativo e monitorar seu desempenho.
É uma excelente opção para desenvolvedores que desejam criar aplicativos excelentes em vez de gerenciar servidores.