Partilhar via


Shiny no Azure Databricks

Shiny é um pacote R, disponível no CRAN, usado para construir aplicativos e painéis interativos R. Você pode usar o Shiny dentro do RStudio Server hospedado em clusters do Azure Databricks. Você também pode desenvolver, hospedar e compartilhar aplicativos Shiny diretamente de um bloco de anotações do Azure Databricks.

Para get começar com o Shiny, consulte os tutoriais . Você pode executar esses tutoriais em blocos de anotações do Azure Databricks.

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

Brilhante dentro de notebooks R

Get começou com Shiny dentro de cadernos R

O pacote Shiny está incluído no Databricks Runtime. Você pode desenvolver e testar interativamente aplicativos Shiny dentro de notebooks do Azure Databricks R de forma semelhante ao RStudio hospedado.

Siga estas etapas para começar a get:

  1. Crie um bloco de anotações R.

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

      library(shiny)
      runExample("01_hello")
    
  3. Quando o aplicativo estiver pronto, a saída incluirá o URL do aplicativo Shiny como um link clicável que abre uma nova guia. Para partilhar esta aplicação com outros utilizadores, consulte Partilhar URL da aplicação Shiny.

    Exemplo de aplicação Shiny

Nota

  • 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 parar o aplicativo Shiny, clique em Cancelar.
  • A aplicação Shiny utiliza o processo R do notebook. Se você desanexar o bloco de anotações do cluster ou cancelar a célula que executa o aplicativo, o aplicativo Shiny será encerrado. Não é possível executar outras células enquanto o aplicativo Shiny está em execução.

Execute aplicativos Shiny a partir de pastas Databricks Git

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

  1. Clone um repositório Git remoto.

  2. Execute a aplicação.

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

Executar aplicações Shiny a partir de ficheiros

Se o código do aplicativo Shiny fizer parte de um projeto gerenciado pelo controle de versão, você poderá executá-lo dentro do bloco de anotações.

Nota

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

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

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

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

Partilhar o URL da aplicação Shiny

O URL do aplicativo Shiny gerado quando você inicia um aplicativo é compartilhável com outros usuários. Qualquer usuário do Azure Databricks com permissão CAN ATTACH TO no cluster pode exibir e interagir com o aplicativo, desde que o aplicativo e o cluster estejam em execução.

Se o cluster no qual o aplicativo está sendo executado for encerrado, o aplicativo não estará mais acessível. Você pode desabilitar a terminação automática nas configurações do cluster.

Se você anexar e executar o bloco de anotações que hospeda o aplicativo Shiny em um cluster diferente, o URL Shiny será alterado. 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, pode-se set a opção shiny.port ou, ao reiniciares a aplicação no mesmo cluster, podes especificar o argumento port.

Brilhante no servidor RStudio hospedado

Requisitos

Importante

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

Get começou com Shiny no servidor RStudio hospedado

  1. Abra o RStudio no Azure Databricks.

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

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

    Um novo window aparece, exibindo o aplicativo Shiny.

    Primeiro aplicativo Shiny

Executar um aplicativo Shiny a partir de um script R

Para executar um aplicativo Shiny a partir 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 brilhante

Use o Apache Spark dentro de aplicativos Shiny

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

Usar o 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)

Use o 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)

Aplicação Spark Shiny

Perguntas mais frequentes (FAQ)

Por que meu aplicativo Shiny está acinzentado depois de algum tempo?

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

Para se reconectar, refresh página do aplicativo Shiny. O estado do painel é redefinido.

Por que o meu visualizador do Shiny window desaparece depois de algum tempo?

Se o visualizador Shiny window desaparecer após estar inativo por vários minutos, é devido ao mesmo limite de tempo que o cenário "cinza".

Por que os trabalhos longos do Spark nunca voltam?

Isso também ocorre por causa do tempo limite ocioso. Qualquer trabalho do Spark em execução por mais tempo do que os tempos limite mencionados anteriormente não é capaz de renderizar seu resultado porque a conexão fecha antes que o trabalho retorne.

Como posso evitar o tempo limite?

  • Há uma solução alternativa sugerida em Solicitação de recurso: fazer com que o cliente envie a mensagem keep alive para evitar o tempo limite de 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 um cálculo de longa execução, essa solução alternativa não funcionará.

  • Shiny não suporta tarefas de longa duração. Uma postagem de blog Shiny recomenda o uso de promessas e futuros para executar tarefas longas de forma assíncrona e manter o aplicativo desbloqueado. Aqui está um exemplo que usa pulsações para manter o aplicativo Shiny vivo e executa um trabalho Spark de longa duração em uma future construção.

    # 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)
    
  • Há um limite rígido de limit de 12 horas a partir do carregamento inicial da página, após o qual qualquer conexão, mesmo que ativa, será encerrada. Você deve refresh o aplicativo Shiny para se reconectar nesses casos. No entanto, a conexão WebSocket subjacente pode fechar 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 para que eles não exijam uma conexão de longa duração e não confiem demais no estado da sessão.

Meu aplicativo falha imediatamente após a inicialização, mas o código parece estar correto. O que é que se passa?

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

A Databricks recomenda até 20.

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

Sim. Consulte Corrigir a versão dos pacotes R.

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

Embora se possa aceder aos dados naturalmente usando o SparkR ou o sparklyr durante o desenvolvimento e teste no Azure Databricks, após uma aplicação Shiny ser publicada num serviço de alojamento autónomo, ela não conseguirá aceder diretamente aos dados e tables no Azure Databricks.

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

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

A 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 existente.

Posso desenvolver um aplicativo Shiny dentro de um bloco de anotações do Azure Databricks?

Sim, você pode desenvolver um aplicativo Shiny dentro de um bloco de anotações do Azure Databricks.

Como posso guardar as aplicações Shiny que desenvolvi no RStudio Server alojado?

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