Share via


Shiny no Azure Databricks

O Shiny é um pacote do R, disponível no Cran, usado para criar painéis e aplicativos R interativos. Você pode usar o Shiny dentro do Servidor do RStudio hospedado em clusters do Azure Databricks. Você também pode desenvolver, hospedar e compartilhar aplicativos Shiny diretamente de um notebook do Azure Databricks.

Para começar a usar o Shiny, confira os tutoriais do Shiny. Você pode executar esses tutoriais em notebooks Azure Databricks.

Este artigo descreve como executar aplicativos Shiny no Azure Databricks e usar o Apache Spark dentro de aplicativos Shiny.

Shiny dentro do bloco de notas do R

Introdução ao Shiny dentro do bloco de notas do R

O pacote Shiny está incluído com Databricks Runtime. Você pode desenvolver e testar interativamente aplicativos Shiny em notebooks R Azure Databricks da mesma forma que no RStudio hospedado.

Siga estas etapas para começar:

  1. Crie um notebook R.

  2. Importe o pacote Shiny e execute o aplicativo de exemplo 01_hello da seguinte maneira:

      library(shiny)
      runExample("01_hello")
    
  3. Quando o aplicativo estiver pronto, a saída incluirá a URL do aplicativo Shiny como um link clicável que abre uma nova guia. Consulte Compartilhar URL do aplicativo Shiny para obter informações sobre como compartilhar esse aplicativo com outros usuários.

    Exemplo de aplicativo Shiny

Observação

  • As mensagens de log aparecem no resultado do comando, semelhante à mensagem de log padrão (Listening on http://0.0.0.0:5150) mostrada no exemplo.
  • Para interromper o aplicativo Shiny, clique em Cancelar.
  • O aplicativo Shiny usa o processo R de notebook. Se você desconectar o notebook do cluster ou se cancelar a célula que está executando o aplicativo, o aplicativo Shiny será encerrado. Não é possível executar outras células enquanto o aplicativo Shiny está em execução.

Executar aplicativos Shiny em pastas Git do Databricks

Você pode executar aplicativos Shiny que são verificados em pastas Git do Databricks.

  1. Clone um repositório remoto do Git.

  2. Execute o aplicativo.

    library(shiny)
    runApp("006-tabsets")
    

Executar aplicativos Shiny desde os arquivos

Se o código do aplicativo Shiny faz parte de um projeto gerenciado pelo controle de versão, você pode executá-lo dentro do notebook.

Observação

Você deve usar o caminho absoluto ou definir o diretório de trabalho com setwd().

  1. Confira o código a partir de um repositório usando código semelhante a:

      %sh git clone https://github.com/rstudio/shiny-examples.git
      cloning into 'shiny-examples'...
    
  2. Para executar o aplicativo, insira em outra célula um código semelhante ao mostrado a seguir:

    library(shiny)
    runApp("/databricks/driver/shiny-examples/007-widgets/")
    

Compartilhar URL do aplicativo Shiny

A URL do aplicativo Shiny gerada quando você inicia um aplicativo é compartilhável com outros usuários. Qualquer usuário do Azure Databricks com permissão PODE ANEXAR AO no cluster pode exibir e interagir com o aplicativo, contanto que tanto o aplicativo quanto o cluster estejam em execução.

Se o cluster em que o aplicativo está sendo executado for encerrado, o aplicativo não será mais acessível. Você pode desabilitar o encerramento automático nas configurações do cluster.

Se você anexar e executar o notebook que hospeda o aplicativo Shiny em um cluster diferente, a URL do Shiny será alterada. Além disso, se você reiniciar o aplicativo no mesmo cluster, o Shiny poderá escolher uma porta aleatória diferente. Para garantir uma URL estável, você pode definir a opção shiny.port ou, ao reiniciar o aplicativo no mesmo cluster, pode especificar o argumento port.

Shiny no RStudio Server hospedado

Requisitos

Importante

Com o RStudio Server Pro, você deve desabilitar a autenticação com proxy. Certifique-se de que auth-proxy=1 não está presente no /etc/rstudio/rserver.conf.

Introdução ao Shiny no RStudio Server hospedado

  1. Abrir o RStudio no Azure Databricks.

  2. No RStudio, importe o pacote Shiny e execute o aplicativo de exemplo 01_hello da seguinte maneira:

    > library(shiny)
    > runExample("01_hello")
    
    Listening on http://127.0.0.1:3203
    

    Uma nova janela é exibida, exibindo o aplicativo Shiny.

    Primeiro aplicativo Shiny

Executar um aplicativo Shiny de um script R

Para executar um aplicativo Shiny de um script R, abra o script R no editor RStudio e clique no botão Executar aplicativo no canto superior direito.

Aplicativo de execução do Shiny

Usar o Apache Spark dentro de aplicativos Shiny

Você pode usar o Apache Spark em aplicativos Shiny com SparkR ou sparklyr.

Usar SparkR com Shiny em um notebook

library(shiny)
library(SparkR)
sparkR.session()

ui <- fluidPage(
  mainPanel(
    textOutput("value")
  )
)

server <- function(input, output) {
  output$value <- renderText({ nrow(createDataFrame(iris)) })
}

shinyApp(ui = ui, server = server)

Usar sparklyr com Shiny em um notebook

library(shiny)
library(sparklyr)

sc <- spark_connect(method = "databricks")

ui <- fluidPage(
  mainPanel(
    textOutput("value")
  )
)

server <- function(input, output) {
  output$value <- renderText({
    df <- sdf_len(sc, 5, repartition = 1) %>%
      spark_apply(function(e) sum(e)) %>%
      collect()
    df$result
  })
}

shinyApp(ui = ui, server = server)
library(dplyr)
library(ggplot2)
library(shiny)
library(sparklyr)

sc <- spark_connect(method = "databricks")
diamonds_tbl <- spark_read_csv(sc, path = "/databricks-datasets/Rdatasets/data-001/csv/ggplot2/diamonds.csv")

# Define the UI
ui <- fluidPage(
  sliderInput("carat", "Select Carat Range:",
              min = 0, max = 5, value = c(0, 5), step = 0.01),
  plotOutput('plot')
)

# Define the server code
server <- function(input, output) {
  output$plot <- renderPlot({
    # Select diamonds in carat range
    df <- diamonds_tbl %>%
      dplyr::select("carat", "price") %>%
      dplyr::filter(carat >= !!input$carat[[1]], carat <= !!input$carat[[2]])

    # Scatter plot with smoothed means
    ggplot(df, aes(carat, price)) +
      geom_point(alpha = 1/2) +
      geom_smooth() +
      scale_size_area(max_size = 2) +
      ggtitle("Price vs. Carat")
  })
}

# Return a Shiny app object
shinyApp(ui = ui, server = server)

Aplicativo Shiny do Spark

Perguntas frequentes (FAQ)

Por que meu aplicativo Shiny fica desativado após algum tempo?

Se não houver nenhuma interação com o aplicativo Shiny, a conexão com o aplicativo será encerrada após cerca de 4 minutos.

Para reconectar, atualize a página de aplicativo Shiny. O estado do painel é redefinido.

Por que minha janela de visualizador do Shiny desaparece após um tempo?

Se a janela de visualizador Shiny desaparecer após vários minutos de ociosidade, isso ocorre devido ao mesmo tempo limite que o cenário "desativado".

Por que trabalhos prolongados do Spark nunca retornam?

Isso também ocorre devido ao tempo limite ocioso. Todo trabalho do Spark em execução por mais tempo do que os tempos limite mencionados anteriormente não é capaz de processar seu resultado porque a conexão é encerrada antes que o trabalho retorne.

Como posso evitar o tempo limite?

  • Há uma solução alternativa sugerida na Solicitação de recurso: fazer com que o cliente envie uma mensagem keep alive para evitar o tempo limite do TCP em alguns balanceadores de carga no Github. A solução alternativa envia pulsações para manter a conexão WebSocket ativa quando o aplicativo está ocioso. No entanto, se o aplicativo estiver bloqueado por uma computação de execução prolongada, essa solução alternativa não funcionará.

  • O Shiny não dá suporte a tarefas de execução prolongada. Uma postagem de blog Shiny recomenda o uso de promessas e futuros para executar tarefas prolongadas de forma assíncrona e manter o aplicativo desbloqueado. Este é um exemplo que usa pulsações para manter o aplicativo Shiny ativo e executa um trabalho do Spark de execução prolongada em uma construção future.

    # Write an app that uses spark to access data on Databricks
    # First, install the following packages:
    install.packages(‘future’)
    install.packages(‘promises’)
    
    library(shiny)
    library(promises)
    library(future)
    plan(multisession)
    
    HEARTBEAT_INTERVAL_MILLIS = 1000  # 1 second
    
    # Define the long Spark job here
    run_spark <- function(x) {
      # Environment setting
      library("SparkR", lib.loc = "/databricks/spark/R/lib")
      sparkR.session()
    
      irisDF <- createDataFrame(iris)
      collect(irisDF)
      Sys.sleep(3)
      x + 1
    }
    
    run_spark_sparklyr <- function(x) {
      # Environment setting
      library(sparklyr)
      library(dplyr)
      library("SparkR", lib.loc = "/databricks/spark/R/lib")
      sparkR.session()
      sc <- spark_connect(method = "databricks")
    
      iris_tbl <- copy_to(sc, iris, overwrite = TRUE)
      collect(iris_tbl)
      x + 1
    }
    
    ui <- fluidPage(
      sidebarLayout(
        # Display heartbeat
        sidebarPanel(textOutput("keep_alive")),
    
        # Display the Input and Output of the Spark job
        mainPanel(
          numericInput('num', label = 'Input', value = 1),
          actionButton('submit', 'Submit'),
          textOutput('value')
        )
      )
    )
    server <- function(input, output) {
      #### Heartbeat ####
      # Define reactive variable
      cnt <- reactiveVal(0)
      # Define time dependent trigger
      autoInvalidate <- reactiveTimer(HEARTBEAT_INTERVAL_MILLIS)
      # Time dependent change of variable
      observeEvent(autoInvalidate(), {  cnt(cnt() + 1)  })
      # Render print
      output$keep_alive <- renderPrint(cnt())
    
      #### Spark job ####
      result <- reactiveVal() # the result of the spark job
      busy <- reactiveVal(0)  # whether the spark job is running
      # Launch a spark job in a future when actionButton is clicked
      observeEvent(input$submit, {
        if (busy() != 0) {
          showNotification("Already running Spark job...")
          return(NULL)
        }
        showNotification("Launching a new Spark job...")
        # input$num must be read outside the future
        input_x <- input$num
        fut <- future({ run_spark(input_x) }) %...>% result()
        # Or: fut <- future({ run_spark_sparklyr(input_x) }) %...>% result()
        busy(1)
        # Catch exceptions and notify the user
        fut <- catch(fut, function(e) {
          result(NULL)
          cat(e$message)
          showNotification(e$message)
        })
        fut <- finally(fut, function() { busy(0) })
        # Return something other than the promise so shiny remains responsive
        NULL
      })
      # When the spark job returns, render the value
      output$value <- renderPrint(result())
    }
    shinyApp(ui = ui, server = server)
    
  • Depois de 12 horas após a carga inicial da página, todas as conexões, mesmo que ativas, serão impreterivelmente encerradas. Você deve atualizar o aplicativo Shiny para se reconectar nesses casos. No entanto, a conexão WebSocket subjacente pode ser fechada a qualquer momento por uma variedade de fatores, incluindo instabilidade de rede ou modo de suspensão do computador. O Databricks recomenda reescrever aplicativos Shiny de modo que eles não exijam uma conexão de longa duração e não dependam demais do estado da sessão.

Meu aplicativo falha imediatamente após a inicialização, mas o código parece estar correto. O que está acontecendo?

Há um limite de 50 MB na quantidade total de dados que podem ser exibidos em um aplicativo Shiny no Azure Databricks. Se o tamanho total dos dados do aplicativo exceder esse limite, ele falhará imediatamente após a inicialização. Para evitar isso, o Databricks recomenda reduzir o tamanho dos dados, por exemplo, diminuindo os dados exibidos ou reduzindo a resolução das imagens.

O Databricks recomenda até 20.

Posso usar uma versão diferente do pacote Shiny do que a instalada no Databricks Runtime?

Sim. Confira Corrigir a versão de pacotes do R.

Como posso desenvolver um aplicativo Shiny que pode ser publicado em um servidor Shiny e acessar dados no Azure Databricks?

Embora você possa acessar os dados naturalmente usando o Sparkr ou o sparklyr durante o desenvolvimento e o teste no Azure Databricks, depois que um aplicativo Shiny é publicado em um serviço de hospedagem autônomo, ele não pode acessar diretamente os dados e as tabelas no Azure Databricks.

Para permitir que seu aplicativo funcione fora do Azure Databricks, você deve reescrever a forma que você acessa os dados. Veja algumas opções:

  • Use JDBC/ODBC para enviar consultas a um cluster do Azure Databricks.
  • Usar o Databricks Connect.
  • Acesse os dados diretamente no armazenamento de objetos.

O Databricks recomenda que você trabalhe com sua equipe de soluções do Azure Databricks para encontrar a melhor abordagem para sua arquitetura de dados e análises existentes.

Posso desenvolver um aplicativo Shiny dentro de um notebook do Azure Databricks?

Sim, é possível desenvolver um aplicativo Shiny dentro de um notebook do Azure Databricks.

Como posso salvar os aplicativos Shiny que desenvolvi no RStudio Server hospedado?

Você pode salvar o código do aplicativo em DBFS ou verificar seu código no controle de versão.