• Posts tagged "AWS"

Blog Archives

2017微软MVP:在AWS上部署免费的Shiny应用

跨界知识聚会系列文章,“知识是用来分享和传承的”,各种会议、论坛、沙龙都是分享知识的绝佳场所。我也有幸作为演讲嘉宾参加了一些国内的大型会议,向大家展示我所做的一些成果。从听众到演讲感觉是不一样的,把知识分享出来,你才能收获更多。

关于作者

  • 张丹, 程序员R,Nodejs,Java
  • weibo:@Conan_Z
  • blog:http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/meeting-mvp-20170723

前言

第一次参加微软的技术日活动,感觉微软已经变得开放了,已不是10年前我所印象的对开源很敌对的微软了。在微软的会场,我主要介绍的是开源技术R语言。

本次的我的主题是AWS和Shiny,Shiny是R语言中一个“神级”的,绝对是好东西;而AWS为全球的开发者提供了免费的服务器,值得赞赏。把这两个好的东西结合在一起,就是一个很好的业务模式,可以极大的帮助个人开发者,来发布自己的作品或产品。

本次所分享的内容为一个实战案例,你可以跟着我的操作,重现我所讲的总有内容。错过沙龙的同学,也可以在天善社区的网站上找到分享的内容。

目录

  1. 我的演讲主题:在AWS上部署免费的Shiny应用
  2. 会议体验和照片分享

1. 我的演讲主题:在AWS上部署免费的Shiny应用

在AWS上部署免费的Shiny应用,PPT下载,主要内容来自我的一篇博文:在AWS上部署免费的Shiny应用

分享主题的目录大纲如下:

  1. Shiny是什么?
  2. 本地开发一个Shiny小应用
  3. 申请AWS免费服务器
  4. 在AWS上安装R语言环境
  5. 在AWS上安装Shiny Server
  6. 在AWS上部署自己的Shiny应用
  7. 番外篇

前6个目录都是正常的技术,番外篇,其实是比较有意思的一个内容。原本我是准备把一个基于赌场原型的Shiny应用放到互联网,考虑服务器位置和选型的问题,无意中发现了AWS的免费资源,这样就有了这样的一篇Shiny与AWS结合的文章。

提问环节时,同学们很热列问了不少的R和Shiny的问题。真的希望大家,动手试一下,R语言一定会给你很棒的体验的。

分享结束后,和几位现场的朋友,聊了中国市场环境与发展机会。感觉到各行各业的人,都体会到了大数据所带来的变化,准备进行大数据的市场,获得更多的商业机会。我觉得中国是有大数据土壤的,而且环境在变好,有越来越多的机会,给留我们去创新和发展。

同时,我也在致力于推动R语言在中国金融领域的发展,让R可以给更多的用户使用,培养出更多的数据分析师。也希望让我们中国人的技术能够走出去到世界的舞台。希望多能认识志同道合的朋友,一起做一些事情。

2. 会议体验和照片分享

本次由5个主题组成,主要是微软的产品技术介绍,毕竟是在人家的主场。

本次微软MVP参加分享的5位嘉宾,主持人 和 微软MVP项目负责人介绍:

吕品,活动介绍 & 现场主持
天善智能联合创始人,微软MVP

Christina,主题:微软项目介绍
China MVP Community Manager

张丹,主题:在AWS上部署免费的Shiny应用,PPT下载
《R的极客理想》系列图书作者,前况客创始人兼CTO。12年IT编程背景,精通R ,Java, Nodejs 编程,获得10项SUN及IBM技术认证。著有《R的极客理想-工具篇》、《R的极客理想-高级开发篇》,合著《数据实践之美》,新书《R的极客理想-量化投资篇》。

刘凯,主题:PowerBI高阶分析:高阶预测分析;DAX万能组合函数的高级应用
IMA中国教育委员会认证讲师,擅长业财融合背景下的数据整合和运营财务分析。曾任职于4A的奥美互动咨询和四大中的KPMG毕博管理咨询,服务于海尔金控等多家客户。

宋卫东,主题:数据仓库运维那些事
从事商业智能数据仓库方向11年,就职某汽车公司,负责数据仓库和大数据等项目。

李奇,主题:Excel BI:无所不能的业务数据分析利器
中国电子表格应用大会主席、曾任职于IBM及德勤会计师事务所,从事业务分析及数据分析咨询工作,Excel BI培训讲师、擅长用Excel创建商业智能报表。

宋沄剑,主题:亿级SQL Server运维的n个最佳实践,PPT下载
微软DataPlatform MVP(since 2012),目前就职于易车网,负责易车数据库与基于Apache生态圈的大数据平台的运维。曾任数据库高级顾问,帮助国内多家客户设计高可用/灾备方案,监控方案、运维自动化方案,并处理SQL Server企业应用实施、日常管理中常见的棘手问题。曾翻译包括SQLServer、PowerShell、Python在内的多本技术书籍,个人技术博客在国内最大的微软社区排名考前,曾多次在数据库大会、Teched、Ignite上分享经验。

嘉宾在分享的照片。

张丹

刘凯

李奇

Christina

宋卫东

宋沄剑

2.2 会议相关照片

本次的场地在微软的北京研发中心,忍不住要说会场很棒,不差钱就是好,干净、整齐、大方。

现场照片

大合照

沙龙很成功,感谢天善社区的工作人员,微软主办方的工作人员,IT大咖说直播的工作人员,大家都辛苦了!祝高质的沙龙,在北京越办越好,让无数有理想的年轻人,能开阔眼界,了解行业动态,推动知识的进步。

转载请注明出处:
http://blog.fens.me/meeting-mvp-20170723

打赏作者

在AWS上部署免费的Shiny应用

R的极客理想系列文章,涵盖了R的思想,使用,工具,创新等的一系列要点,以我个人的学习和体验去诠释R的强大。

R语言作为统计学一门语言,一直在小众领域闪耀着光芒。直到大数据的爆发,R语言变成了一门炙手可热的数据分析的利器。随着越来越多的工程背景的人的加入,R语言的社区在迅速扩大成长。现在已不仅仅是统计领域,教育,银行,电商,互联网….都在使用R语言。

要成为有理想的极客,我们不能停留在语法上,要掌握牢固的数学,概率,统计知识,同时还要有创新精神,把R语言发挥到各个领域。让我们一起动起来吧,开始R的极客理想。

关于作者:

  • 张丹(Conan), 程序员Java,R,PHP,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/r-shiny-aws/

前言

无意中发现了AWS的提供免费的服务器资源,必须要大赞一下,写篇文章大大的推广。

Shiny是R语言中一个神级的应用,唯一的缺点就是不支持并发。所以,我们很多时候都是做本地Shiny应用,用于展示各种报表的效果。但有时候也需要把报表上传到互联网上,其他人也能看到。这样就需要一个互联网的解决方案,刚好AWS有了免费的服务器支持。简直是完美!!

目录

  1. Shiny是什么?
  2. 本地开发一个Shiny小应用
  3. 申请AWS免费服务器
  4. 在AWS上安装R语言环境
  5. 在AWS上安装Shiny Server
  6. 在AWS上部署自己的Shiny应用

1. Shiny是什么?

Shiny是RStudio公司开发的,一个用于R语言的Web应用程序框架,可以轻松开发交互式web应用,不需要了解HTML, CSS, JS等前端知识。

Shiny构建出应用的惊艳程度,远远超过了说明的文字。一定要学学,下面是一个Shiny小程序的截图。

Shiny的主页:http://shiny.rstudio.com/

我们安装Shiny可以直接从CRAN获取,通过一行R程序就可以安装了。


~ R
> install.packages("shiny")

2. 本地开发一个Shiny小应用

下面我们用Shiny开发一个小应用的实例,主要是为介绍Shiny的用法,包括网页的界面UI和后端程序,数据源使用R语言自带的一个数据集。

数据集是faithful,统计的是美国黄石国家公园的泉水(Old Faithful geyser) 喷发的持续时间和喷发等待时间 。

包括2列,eruptions为喷发持续时间,waiting为喷发的等待时间。


> head(faithful,20)
   eruptions waiting
1      3.600      79
2      1.800      54
3      3.333      74
4      2.283      62
5      4.533      85
6      2.883      55
7      4.700      88
8      3.600      85
9      1.950      51
10     4.350      85
11     1.833      54
12     3.917      84
13     4.200      78
14     1.750      47
15     4.700      83
16     2.167      52
17     1.750      62
18     4.800      84
19     1.600      52
20     4.250      79

开发环境所使用的系统环境

  • Win10 64bit
  • R: 3.2.3 x86_64-w64-mingw32/x64 b4bit

Shiny应用,分为定义了客户端程序ui.R,和服务器端程序server.R,这2个文件默认要求放同一个目录中。另外,我们还需要一个启动文件run.R,用于启动Shiny的应用。当然,如果在RStudio中开发,就不需要run.R的文件,直接点Shiny应用的启动按钮就行了。

开始创建项目目录和文件。


~ cd D:\workspace\dash
~ mkdir demo1
~ notepad run.R
~ cd demo1
~ notepad server.R
~ notepad ui.R

目录结构如下:


D:\workspace\dash
|--run.R
|--demo1
   |--server.R
   |--ui.R

编辑文件:run.R


library("shiny")
runApp("./demo1",host='127.0.0.1',port=3840)

编辑文件:server.R


library(shiny)

shinyServer(function(input, output) {

  # 输出到UI的main_plot
  output$main_plot <- renderPlot({
    
    # 直方图
    hist(faithful$eruptions,
         probability = TRUE,
         breaks = as.numeric(input$n_breaks),
         xlab = "持续时间",
         main = "喷发持续时间")
    
    # 是否显示individual_obs
    if (input$individual_obs) {
      rug(faithful$eruptions)
    }
    
    # 是否显示conditionalPanel
    if (input$density) {
      dens <- density(faithful$eruptions, adjust = input$bw_adjust)
      lines(dens, col = "blue")
    }
    
  })
})

编辑文件:ui.R


library(shiny)
shinyUI(bootstrapPage(
  
  headerPanel("第一个Shiny应用"),
  
  # 左侧布局
  sidebarPanel(
    
    # 下拉框
    selectInput(inputId = "n_breaks",label = "直方图中的分隔数",choices = c(10, 20, 35, 50),selected = 20),
    
    # 单选框
    checkboxInput(inputId = "individual_obs",label = strong("实际观察点"),value = FALSE),
    
    # 单选框
    checkboxInput(inputId = "density",label = strong("密度估计曲线"),value = FALSE)
  ),
  
  # 主布局
  mainPanel(
    plotOutput(outputId = "main_plot", height = "300px"),
    
    conditionalPanel(condition = "input.density == true",
                     sliderInput(inputId = "bw_adjust",label = "带宽调整", min = 0.2, max = 2, value = 1, step = 0.2)
    )
  )
))

启动Shiny应用时,本地的3840端口,就被打开了。


~ D:\workspace\dash>R -f run.r
R version 3.2.3 (2015-12-10) -- "Wooden Christmas-Tree"
Copyright (C) 2015 The R Foundation for Statistical Computing
Platform: x86_64-w64-mingw32/x64 (64-bit)
R
'license()''licence()'
R.
'contributors()'
'citation()'RR
'demo()''help()'
'help.start()'HTML
'q()'R.

> library("shiny")
> runApp("./demo1",host='127.0.0.1',port=3840)

Listening on http://127.0.0.1:3840

我们可以用浏览器,来访问本地的服务 http://127.0.0.1:3840 。

这是一个标准的Web网页,如果我们操作网页上的表单元素,对应该的数据也会发生变化了。这样我们就完成了一个本的Shiny的小应用的开发,接下来就是把这个程序部署到AWS上面了。

3. 申请AWS免费服务器

AWS是Amazon提供的一个云服务平台,利用亚马逊 AWS,软件开发人员可以轻松购买计算、存储、数据库和其他基于 Internet 的服务来支持其应用程序。开发人员能够灵活选择任何开发平台或编程环境,以便于其尝试解决问题。由于开发人员只需按使用量付费,无需前期资本支出,亚马逊 AWS 是向最终用户交付计算资源、保存的数据和其他应用程序的一种最经济划算的方式。

AWS有一个免费的套餐,让互联网用户可以免费的使用他的资源,包括了服务器,数据库,CDN,负载均衡等服务。我们为了部署自己的Shiny应用,可以申请免费的服务器资源,先跑一下,看看效果。

首先,你需要注册一个AWS账号,然后登录进去,选择地区,申请免费的服务器。目前免费开放的区域不包括中国区,我选择了一个日本东京的服务器,Ubuntu Linux 64bit。

免费的资源,有一些限制,只能1核心CPU,1G内存,最大30G存储等。当然了,有免费的资源,已经是很棒的了,而且是AWS的服务。

接下来,就是做资源配置,然后就可以启动服务器了。

大概等3分钟,服务器启动完成,然后就可以通过SSH进行访问了。

AWS为了保证安全性,建议使用秘钥访问,而不是直接的用户名和密码的方式,所以你需要创建一个秘钥对,下载一个xx.pem的私钥,然后配到Putty或XShell等用于远程登录的客户端里。

然后,就可以用XShell连接,免费创建的EC2的服务器了。在这里,如果是Ubuntu的Linux服务器,用户名需要使用ubuntu,不能直接设置root。

4. 安装R语言环境

登录后,我们就可以安装R语言的环境了。安装过程比较简单,如果你需要装指定版本的R软件,那么你需要参考文章,R的历史版本安装。如果是安装默认版本的R语言环境,直接使用是apt-get命令就是最方便的。

服务器所使用的系统环境

  • Linux Ubuntu 16.04.2 LTS 64-bit
  • R: 3.2.3 x86_64-pc-linux-gnu (64-bit)

我们先更新apt的软件源,安装必备的系统软件,包括r-base和git,以及的Shiny应用的依赖库libcurl4-openssl-dev,libxml2-dev。如果你忘了装了,后面再装也都不影响。


~ sudo apt-get update
~ sudo apt-get install r-base
~ sudo apt-get install git
~ sudo apt-get install libcurl4-openssl-dev
~ sudo apt-get install libxml2-dev

接下来,让我们安装R语言的依赖包。这里有一个小技巧,就是在R语言的环境中安装第三方R包,并切换成root用户。


~ sudo -i  # 切换成root用户
~ R        # 启动R语言环境

我们需要预装的包,主要就是shiny,当然如果你还有依赖其他的包,都可以一块安装。安装时,R会让我们选择软件源,如果用https协议的镜像列表,你需要配置一下curl进行下载。你依然可以选择用http协议的镜像列表,选61之后,会出现http的镜像列表。

我们的服务器在Tokyo,所以也选择Tokyo的镜像列表,然后开始下载R的第三方软件包。


# 安装包
> install.packages("shiny")

Installing package into ‘/usr/local/lib/R/site-library’
(as ‘lib’ is unspecified)
--- Please select a CRAN mirror for use in this session ---
HTTPS CRAN mirror 

 1: 0-Cloud [https]                 2: Algeria [https]              
 3: Australia (Canberra) [https]    4: Australia (Melbourne) [https]
 5: Australia (Perth) [https]       6: Austria [https]              
25: France (Montpellier) [https]   26: France (Paris 2) [https]     
27: Germany (Göttingen) [https]    28: Germany (Münster) [https]    
29: Greece [https]                 30: Iceland [https]              
31: India [https]                  32: Indonesia (Jakarta) [https]  
33: Ireland [https]                34: Italy (Padua) [https]        
35: Japan (Tokyo) [https]          36: Malaysia [https]             
61: (HTTP mirrors)                 

Selection: 61

HTTP CRAN mirror 

 1: 0-Cloud                       2: Algeria                    
 3: Argentina (La Plata)          4: Australia (Canberra)       
 5: Austria                       6: Belgium (Antwerp)          
 7: Belgium (Ghent)               8: Brazil (BA)                
 9: Brazil (PR)                  10: Brazil (RJ)                
11: Brazil (SP 1)                12: Brazil (SP 2)              
13: Bulgaria                     14: Canada (BC)                
37: Hungary                      38: Iceland                    
39: India                        40: Iran                       
41: Ireland                      42: Italy (Milano)             
43: Italy (Padua)                44: Italy (Palermo)            
45: Japan (Tokyo)                46: Korea (Seoul 1)            
47: Korea (Seoul 2)              48: Korea (Ulsan)                          
89: USA (TX 1)                   90: Venezuela   

Selection: 45

顺利安装完R的依赖包,接下来就是要安装Shiny Server了。Shiny Server是一个单独的软件,目前还不支持通过apt-get或R本身进行安装,需要下载安装。

5. 安装Shiny Server

在开发时,我们其实只是用到了shiny的R语言第三方包,可以在本地的开发环境,运行Shiny的程序。那么,如果把一个Shiny放到公司内网或外网给其他人用呢?这时就是需要Shiny Server了。

Shiny Server提供一个稳定的Shiny应用在线的运行环境,Shiny Server分成开源版本和企业版本。开源版本,提供了基本的Shiny功能,数据、可视化、运行环境,对于个人来说已经足够用了,而且非常友好。企业版本,提供安全和管理功能添加到基本的开源版本中。RStudio公司出品,必属精品!!

Shiny Server是一个单独的软件,我们需要下载进行安装,下载地址:https://www.rstudio.com/products/shiny/shiny-server/

在Ubuntu的环境中,我们可以通过下面的命令,进行下载和安装。


~ sudo apt-get install gdebi-core
~ wget https://download3.rstudio.org/ubuntu-12.04/x86_64/shiny-server-1.5.3.838-amd64.deb
~ sudo gdebi shiny-server-1.5.3.838-amd64.deb

Reading package lists... Done
Building dependency tree        
Reading state information... Done
Reading state information... Done

Shiny Server
 Shiny Server is a server program from RStudio, Inc. that makes Shiny applications available over the web. Shiny is a web application framework for the R statistical computation language.
Do you want to install the software package? [y/N]:y
Selecting previously unselected package shiny-server.
(Reading database ... 63176 files and directories currently installed.)
Preparing to unpack shiny-server-1.5.3.838-amd64.deb ...
Unpacking shiny-server (1.5.3.838) ...
Setting up shiny-server (1.5.3.838) ...
Creating user shiny
Adding LANG to /etc/systemd/system/shiny-server.service, setting to en_US.UTF-8
Created symlink from /etc/systemd/system/multi-user.target.wants/shiny-server.service to /etc/systemd/system/shiny-server.service.
● shiny-server.service - ShinyServer
   Loaded: loaded (/etc/systemd/system/shiny-server.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2017-07-06 07:40:24 UTC; 6ms ago
  Process: 25322 ExecStartPost=/bin/sleep 3 (code=exited, status=0/SUCCESS)
 Main PID: 25325 (shiny-server)
    Tasks: 12
   Memory: 35.4M
      CPU: 411ms
   CGroup: /system.slice/shiny-server.service
           ├─25321 /bin/bash -c /opt/shiny-server/bin/shiny-server --pidfile=/var/run/shiny-server.pid >> /var/log...
           └─25325 /opt/shiny-server/ext/node/bin/shiny-server /opt/shiny-server/lib/main.js --pidfile=/var/run/sh...

Jul 06 07:40:21 ip-172-31-31-236 systemd[1]: Starting ShinyServer...
Jul 06 07:40:24 ip-172-31-31-236 systemd[1]: shiny-server.service: Supervising process 25325 which is not our...xits.
Jul 06 07:40:24 ip-172-31-31-236 systemd[1]: Started ShinyServer.
Hint: Some lines were ellipsized, use -l to show in full.

运行完安装的命令,默认情况Shiny Server会被直接启动起来,其中3838的端口被打开。

检查启动端口


~ netstat -nlpt
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -               
tcp        0      0 0.0.0.0:3838            0.0.0.0:*               LISTEN      -               
tcp6       0      0 :::22                   :::*                    LISTEN      -               

我们可以通过浏览器,直接基于IP和端口进行Shiny Server的访问了。

打开的页面是默认的Shiny Server的网页,如果和上面的截图一样,说明你的Shiny Server安装成功了。

提醒一下,AWS的EC2的主机,一定要配置网络访问策略,打开3838端口,允许外部访问,不然一直都是无法访问此网站的错误。

6. 部署自己的Shiny应用

还差最后一步,就是把我们自己开发的Shiny应用,部署到AWS的EC2上面。代码上传的过程,我们可以基于github来完成。

操作过程如下:

  1. 在github上面,新建一个项目,名为shiny-demo。
  2. 把本地开发的代码,上传到github的shiny-demo项目中。
  3. 在AWS的EC2上,从github的shiny-demo项目中,下载代码。
  4. 在AWS的EC2上,修改Shiny Server的配置,加载项目代码。
  5. 在AWS的EC2上,重启Shiny Server,发现错误。
  6. 在AWS的EC2上,查看日志修复错误。
  7. 在浏览器上访问,自己的Shiny应用。

6.1. 在github上面创建项目,名为shiny-demo。

github操作过程省略。项目地址 https://github.com/bsspirit/shiny-demo

6.2 把本地开发的代码,上传到github的shiny-demo项目中。

切换到本地开发的环境。


~ cd d:\workspace\dash
~ git init
~ git add .
~ git commit -m 'init'
~ git remote add origin https://github.com/bsspirit/shiny-demo.git
~ git push -u origin master  

6.3 在AWS的EC2上,从github的shiny-demo项目中,下载代码。

切换到服务器环境。


# 查看当前目录
~ pwd
/home/ubuntu

# 下载github项目
~ git clone https://github.com/bsspirit/shiny-demo
Cloning into 'shiny-demo'...
remote: Counting objects: 12, done.
remote: Compressing objects: 100% (11/11), done.
remote: Total 12 (delta 0), reused 12 (delta 0), pack-reused 0
Unpacking objects: 100% (12/12), done.
Checking connectivity... done.

# 查看项目文件
~ cd shiny-demo
~ tree
.
├── demo1
│   ├── server.R
│   └── ui.R
├── README.md
└── run.r

1 directory, 4 files

6.4 在AWS的EC2上,修改Shiny Server的配置,加载项目代码。

编辑shiny-server的配置文件shiny-server.conf。


~ sudo vi /etc/shiny-server/shiny-server.conf

# Instruct Shiny Server to run applications as the user "shiny"
run_as shiny;

# Define a server that listens on port 3838
server {
  listen 3838;

  # Define a location at the base URL
  location / {

    # Host the directory of Shiny Apps stored in this directory
    site_dir /srv/shiny-server;

    # Log all Shiny output to files in this directory
    log_dir /var/log/shiny-server;

    # When a user visits the base URL rather than a particular application,
    # an index of the applications available in this directory will be shown.
    directory_index on;
  }

  # 新增加指向github的代码位置
  location /demo1 {
    app_dir /home/ubuntu/shiny-demo/demo1;
    log_dir /var/log/shiny-server/demo1;
  }
}

增加 location /demo1 { } 的配置部分,用来把自己的Shiny的应用,在Shiny Server中进行注册。当然,对于不熟悉Shiny Server的配置的人,可以参考Shiny Server的管理员使用手册 http://docs.rstudio.com/shiny-server/

6.5 在AWS的EC2上,重启Shiny Server,发现错误。

重启Shiny Server,虽然只是重启,但经常出现错误。


~ sudo service shiny-server restart

# 对于Ubuntu 15.04+的系统,推荐用下面的命令。
~ sudo systemctl restart shiny-server

重启后,就可以在浏览器上,访问自己的Shiny应用了。

打开以后,出现了一个错误页面,这种情况太正常了。会出现各种各样的异常的情况,然后就需要我们反复进行调试了。

6.6 在AWS的EC2上,查看日志,修复错误。

主要的调试的方法,就是检查Shiny Server的日志。日志在设置上,有一个很大的坑,我也是在挠头搞了3个小时后才发现的。

由于Shiny Server为了保证性能,所以非敏感性的错误日志被设置了自动清除,每当你出现了错误,要去看日志定位问题的时候,这个日志就刚好被自动清除了。坑很大!!都开始怀疑人生了。

所以,你在调试时需要修改一个参数,保证日志不会被自动清除。

修改文件shiny-server.conf


~ sudo vi /etc/shiny-server/shiny-server.conf

run_as shiny;

access_log /var/log/shiny-server/access.log default;  # 增加记录访问
preserve_logs true;                                   # 禁止自动清除日志

# Define a server that listens on port 3838
server {
  listen 3838;

# 省略
}

再次重启Shiny Server。


~ sudo systemctl restart shiny-server

发现问题,检查日志,然后,我们对应日志的解决问题。


~ sudo cat /var/log/shiny-server/demo1/demo1-shiny-20170706-081120-42749.log 

Listening on http://127.0.0.1:42749
Warning: Error in if: argument is of length zero
Stack trace (innermost first):
    101: density.default
    100: density
     99: renderPlot [/home/ubuntu/shiny-demo/demo1/server.R#22]
     89: 
     78: plotObj
     77: origRenderFunc
     76: output$main_plot
      1: runApp

很多情况下,诡异的错误都是缺少第三方包造成的,当你程序中使用了第三包的时候,一直要记得在Shiny的服务器上面安装好。记得用root用户!!

总结一下,我们利用免费的AWS的EC2服务器资源,发布了自己的Shiny应用,是多么的开心啊!这样以后就可以大胆地去开发自己喜欢的Shiny应用了,当然不只是Shiny应用,你可以利用AWS的免费资源,做更多的事情。老司机,都明白的!!

原本是准备把一个基于赌场原型的Shiny应用放到互联网,考虑服务器位置和选型的问题,无意中发现了AWS的免费资源,这样就有了这样的一篇Shiny与AWS结合的文章。下一篇,要不要分析一下赌场的模型呢。

转载请注明出处:
http://blog.fens.me/r-shiny-aws/

打赏作者

构建自己的Aleax查询服务

从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。Nodejs标准的web开发框架Express,可以帮助我们迅速建立web站点,比起PHP的开发效率更高,而且学习曲线更低。非常适合小型网站,个性化网站,我们自己的Geek网站!!

关于作者

  • 张丹(Conan), 程序员Java,R,Javascript
  • weibo:@Conan_Z
  • blog: http://blog.fens.me
  • email: bsspirit@gmail.com

转载请注明出处:
http://blog.fens.me/nodejs-alexa/

alexa-title

前言

每个网站的站长都会想尽办法提升网站的流量,从而获得更高的广告收入。那么评判一个网站好坏的标准,如Google的PR(PageRank),百度权重等。从PV(Page View)流量的角度,一个非常重要指标就是Alexa网站排名。

同全球的网站相比,你就能了解到自己网站的位置,让我们先挤进全球前10万的排名吧,不然都不好意思跟同行说,“自己有一个网站”。

目录

  1. Alexa介绍
  2. 用Node开发Alexa服务

1. Alexa介绍

Alexa (http://www.alexa.com/)是一家发布世界网站排名的网站,以搜索引擎起家的Alexa创建于1996年4月(美国),目的是让互联网网友在分享虚拟世界资源的同时,更多地参与互联网资源的组织。Alexa每天在网上搜集超过1TB的信息,不仅给出多达几十亿的网址链接,而且为其中的每一个网站进行了排名。可以说,Alexa是当前拥有URL数量最庞大,排名信息发布最详尽的网站。

1999年,Alexa被美国电子商务旗舰企业“亚马逊”收购,成为后者的全资子公司。2002年春,Alexa放弃了自己的搜索引擎,转而与Google合作。

Alexa提供了网站流量统计的服务,对全球有域名的网站进行流量记录。也就是说,只要你申请了域名,在Alexa中就可以查询到你的网站的排名。Alexa的网站排名是按照每个特定网站的被浏览率进行排名的。浏览率越大,排名越靠前。

fens

通常情况,如果你的域名刚刚注册,排名在1千万以上;接下来,你每天都经心运营网站,小有起色时,排名会进入前1百万;然后,你继续发布优质内容,坚持了一段时间,排名会升至前50万;当你的网站在某一领域小有名气时,排名可以到达10万,如粉丝日志122616(2015-10-25),这时就会有广告主愿意来投放广告了;如果你做的是以盈利为目的的网站,那么你需要再加油,进入到前1万,这个时候你的流量已经可以为你带来生意了;如果能做的更好,排名进入前2000,像雪球排名到2109(2015-10-25),那么你将会有一个很高的估值了;如果赶上一个天大的机遇,你的网站排名到了前100,那么你的网站将给你带来上市公司的价值,如京东105(2015-10-25);如果你是天才型的CEO,网站进了前10名,那么你将会成为一个产业的领袖,甚至是某个区域的首富,如百度4(2015-10-25)。

站长们,加油!

2. 用Node开发Alexa服务

2.1 Alexa开放API

Alexa网站排名被业界普通的认可,排名数据会经常地被引用,每次都在网站上查询就会显得不方便。Amazon提供的Alexa的API,让开发者可以构建自己的Alexa查询的应用。

Alexa有2个主要的数据API服务。

通常情况,只需要调用UrlInfo数据接口,就可以获得网站的流量数据了。当然,这个接口的定义,并不像我之前想象的那么好用,而且开放出来的数据有限。

UrlInfo接口的API,如下图所示。

urlinfo

官方提供了多语言的SDK工具包,我觉得还是Node.js最方便。我构建的一个Alexa数据查询服务,http://fens.me/alexa


fens2

2.2 创建AWS的API密钥

我们在使用AWS的API之前,需要先创建密钥,类似于OAuth2的访问的机制。

1. 注册AWS账号,请大家自己完成。注册
2. 进入AWS账号管理控制台,控制台

3. 从控制台选择“安全证书”
aws1

4. 创建访问密钥(访问密钥 ID 和私有访问密钥)

aws2

我们一会写程序的时候,需要输入创建的访问密钥 ID 和私有访问密钥。

2.3 用Node开发Alexa服务

接下来,介绍用Node构建一个Alexa的项目。

我的系统环境

  • Win10 64bit
  • Node v0.12.3
  • NPM 2.9.1

创建项目


~ D:\workspace\nodejs>mkdir nodejs-alexa && cd nodejs-alexa

新建Node项目配置文件:package.json


~ vi package.json

{
  "name": "alexa-demo",
  "version": "0.0.1",
  "description": "alexa web demo",
  "license": "MIT",
  "dependencies": {
    "awis": "0.0.8"
  }
}

安装awis包


~ D:\workspace\nodejs\nodejs-alexa>npm install
npm WARN package.json alexa-demo@0.0.1 No repository field.
npm WARN package.json alexa-demo@0.0.1 No README data
alexarank@0.1.1 node_modules\alexarank
├── xml2js@0.4.13 (sax@1.1.4, xmlbuilder@3.1.0)
└── request@2.30.0 (forever-agent@0.5.2, aws-sign2@0.5.0, qs@0.6.6, tunnel-agent@0.3.0, oauth-sign@0.3.0, json-stringify-safe@5.0.1, mime@1.2.11, node-uuid@1.4.3, tough-cookie@0.9.15, form-data@0.1.4, hawk@1.0.0, http-signature@0.10.1)

awis@0.0.8 node_modules\awis
├── xml2js@0.4.13 (sax@1.1.4, xmlbuilder@3.1.0)
├── lodash@3.10.1
└── request@2.65.0 (aws-sign2@0.6.0, forever-agent@0.6.1, caseless@0.11.0, stringstream@0.0.4, oauth-sign@0.8.0, tunnel-agent@0.4.1, isstream@0.1.2, json-stringify-safe@5.0.1, extend@3.0.0, node-uuid@1.4.3, qs@5.2.0, tough-cookie@2.2.0, combined-stream@1.0.5, mime-types@2.1.7, form-data@1.0.0-rc3, http-signature@0.11.0, hawk@3.1.0, bl@1.0.0, har-validator@2.0.2)

新建文件alexa.js,调用AWS Alexa网站排名API。


~ vi alexa.js

// 定义AWS密钥
var key = 'xxxxxxxxxxxxxxx';
var sercet = 'xxxxxxxxxxxxxxx';

// 创建awis实例化对象
var awis = require('awis');
var client = awis({
  key: key,
  secret: sercet
});

// 调用UrlInfo接口
console.log("=============UrlInfo=================");
client({
  'Action': 'UrlInfo',                         //UrlInfo接口
  'Url': 'fens.me',                            //查询的网站
  'ResponseGroup': 'TrafficData,ContentData'   //需要的数据组
}, function (err, data) {
  if(err) console.log(err);
  console.log(data);  
});

运行程序node alexa.js


~ D:\workspace\nodejs\nodejs-alexa>node alexa.js
=============UrlInfo=================
{ contentData:
   { dataUrl: 'fens.me',
     siteData:
      { title: '粉丝日志',
        description: '跨界的IT博客|Hadoop家族, R, RHadoop, Nodejs, AngularJS, NoSQL, IT金融' },
     speed: { medianLoadTime: '982', percentile: '70' },
     adultContent: '',
     language: '',
     linksInCount: '198',
     keywords: '',
     ownedDomains: '' },
  trafficData:
   { dataUrl: 'fens.me',
     rank: '122616',
     usageStatistics: { usageStatistic: [Object] },
     contributingSubdomains: { contributingSubdomain: [Object] } } }

简简单单地几行代码,都获得了Alexa的排名信息。后台打印时Object没有转到成对象,我做了一个服务,可以通过HTTP输出查看完整的返回。http://api.fens.me/alexa/fens.me

我们查检一下awis包的源代码可以发现,其实AWS Alexa服务返回是XML,awis的自动帮我们做了JSON的转型处理,如果想查看原始的返回值,可以修改awis包中index.js文件parse()函数。


function parse(xml, req, cb) {
  console.log(xml); //打印

  ....
}

运行程序


D:\workspace\nodejs\nodejs-alexa>node alexa.js
=============UrlInfo=================
<?xml version="1.0"?>
<aws:UrlInfoResponse xmlns:aws="http://alexa.amazonaws.com/doc/2005-10-05/"><aws:Response xmlns:aws="http://awis.amazonaws.com/doc/2005-07-11"><aws:OperationRequest><aws:RequestId>1e7d8406-4b62-3460-27fb-325fc3dc3e85</aws:RequestId></aws:OperationRequest><aws:UrlInfoResult><aws:Alexa>

  <aws:ContentData>
    <aws:DataUrl type="canonical">fens.me</aws:DataUrl>
    <aws:SiteData>
      <aws:Title>粉丝日志</aws:Title>
      <aws:Description>跨界的IT博客|Hadoop家族, R, RHadoop, Nodejs, AngularJS, NoSQL, IT金融</aws:Description>
    </aws:SiteData>
    <aws:Speed>
      <aws:MedianLoadTime>982</aws:MedianLoadTime>
      <aws:Percentile>70</aws:Percentile>
    </aws:Speed>
    <aws:AdultContent/>
    <aws:Language/>
    <aws:LinksInCount>198</aws:LinksInCount>
    <aws:Keywords/>
    <aws:OwnedDomains/>
  </aws:ContentData>
  <aws:TrafficData>
    <aws:DataUrl type="canonical">fens.me</aws:DataUrl>
    <aws:Rank>122616</aws:Rank>
    <aws:UsageStatistics>
      <aws:UsageStatistic>
        <aws:TimeRange>
          <aws:Months>3</aws:Months>
        </aws:TimeRange>
        <aws:Rank>
          <aws:Value>122616</aws:Value>
          <aws:Delta>+28849</aws:Delta>
        </aws:Rank>
        <aws:Reach>
          <aws:Rank>
            <aws:Value>110056</aws:Value>
            <aws:Delta>+25785</aws:Delta>
          </aws:Rank>
          <aws:PerMillion>
            <aws:Value>12.5</aws:Value>
            <aws:Delta>-24.68%</aws:Delta>
          </aws:PerMillion>
        </aws:Reach>
        <aws:PageViews>
          <aws:PerMillion>
            <aws:Value>0.27</aws:Value>
            <aws:Delta>-24.84%</aws:Delta>
          </aws:PerMillion>
          <aws:Rank>
            <aws:Value>194189</aws:Value>
            <aws:Delta>43945</aws:Delta>
          </aws:Rank>
          <aws:PerUser>
            <aws:Value>1.9</aws:Value>
            <aws:Delta>0%</aws:Delta>
          </aws:PerUser>
        </aws:PageViews>
      </aws:UsageStatistic>
      <aws:UsageStatistic>
        <aws:TimeRange>
          <aws:Months>1</aws:Months>
        </aws:TimeRange>
        <aws:Rank>
          <aws:Value>102621</aws:Value>
          <aws:Delta>-30257</aws:Delta>
        </aws:Rank>
        <aws:Reach>
          <aws:Rank>
            <aws:Value>95663</aws:Value>
            <aws:Delta>-20326</aws:Delta>
          </aws:Rank>
          <aws:PerMillion>
            <aws:Value>15</aws:Value>
            <aws:Delta>+20%</aws:Delta>
          </aws:PerMillion>
        </aws:Reach>
        <aws:PageViews>
          <aws:PerMillion>
            <aws:Value>0.37</aws:Value>
            <aws:Delta>+60%</aws:Delta>
          </aws:PerMillion>
          <aws:Rank>
            <aws:Value>153976</aws:Value>
            <aws:Delta>-69981</aws:Delta>
          </aws:Rank>
          <aws:PerUser>
            <aws:Value>2.2</aws:Value>
            <aws:Delta>+30%</aws:Delta>
          </aws:PerUser>
        </aws:PageViews>
      </aws:UsageStatistic>
      <aws:UsageStatistic>
        <aws:TimeRange>
          <aws:Days>7</aws:Days>
        </aws:TimeRange>
        <aws:Rank>
          <aws:Value>114709</aws:Value>
          <aws:Delta>+32390</aws:Delta>
        </aws:Rank>
        <aws:Reach>
          <aws:Rank>
            <aws:Value>103552</aws:Value>
            <aws:Delta>+27312</aws:Delta>
          </aws:Rank>
          <aws:PerMillion>
            <aws:Value>14</aws:Value>
            <aws:Delta>-28.59%</aws:Delta>
          </aws:PerMillion>
        </aws:Reach>
        <aws:PageViews>
          <aws:PerMillion>
            <aws:Value>0.3</aws:Value>
            <aws:Delta>-37.28%</aws:Delta>
          </aws:PerMillion>
          <aws:Rank>
            <aws:Value>188124</aws:Value>
            <aws:Delta>58655</aws:Delta>
          </aws:Rank>
          <aws:PerUser>
            <aws:Value>2.0</aws:Value>
            <aws:Delta>-12.11%</aws:Delta>
          </aws:PerUser>
        </aws:PageViews>
      </aws:UsageStatistic>
      <aws:UsageStatistic>
        <aws:TimeRange>
          <aws:Days>1</aws:Days>
        </aws:TimeRange>
        <aws:Rank>
          <aws:Value>74860</aws:Value>
          <aws:Delta>-93163</aws:Delta>
        </aws:Rank>
        <aws:Reach>
          <aws:Rank>
            <aws:Value>70563</aws:Value>
            <aws:Delta>-54001</aws:Delta>
          </aws:Rank>
          <aws:PerMillion>
            <aws:Value>20</aws:Value>
            <aws:Delta>+60%</aws:Delta>
          </aws:PerMillion>
        </aws:Reach>
        <aws:PageViews>
          <aws:PerMillion>
            <aws:Value>0.6</aws:Value>
            <aws:Delta>+300%</aws:Delta>
          </aws:PerMillion>
          <aws:Rank>
            <aws:Value>111541</aws:Value>
            <aws:Delta>-210757</aws:Delta>
          </aws:Rank>
          <aws:PerUser>
            <aws:Value>2</aws:Value>
            <aws:Delta>+100%</aws:Delta>
          </aws:PerUser>
        </aws:PageViews>
      </aws:UsageStatistic>
    </aws:UsageStatistics>
    <aws:ContributingSubdomains>
      <aws:ContributingSubdomain>
        <aws:DataUrl>blog.fens.me</aws:DataUrl>
        <aws:TimeRange>
          <aws:Months>1</aws:Months>
        </aws:TimeRange>
        <aws:Reach>
          <aws:Percentage>99.19%</aws:Percentage>
        </aws:Reach>
        <aws:PageViews>
          <aws:Percentage>99.64%</aws:Percentage>
          <aws:PerUser>2.2</aws:PerUser>
        </aws:PageViews>
      </aws:ContributingSubdomain>
      <aws:ContributingSubdomain>
        <aws:DataUrl>OTHER</aws:DataUrl>
        <aws:TimeRange>
          <aws:Months>1</aws:Months>
        </aws:TimeRange>
        <aws:Reach>
          <aws:Percentage>0</aws:Percentage>
        </aws:Reach>
        <aws:PageViews>
          <aws:Percentage>0.36%</aws:Percentage>
          <aws:PerUser>0</aws:PerUser>
        </aws:PageViews>
      </aws:ContributingSubdomain>
    </aws:ContributingSubdomains>
  </aws:TrafficData>
</aws:Alexa></aws:UrlInfoResult><aws:ResponseStatus xmlns:aws="http://alexa.amazonaws.com/doc/2005-10-05/"><aws:StatusCode>Success</aws:StatusCode></aws:ResponseStatus></aws:Response></aws:UrlInfoResponse>

除了UrlInfo接口还有几个接口可以使用。

TrafficHistory接口


console.log("=============TrafficHistory=================");
client({
  'Action': 'TrafficHistory',
  'Url': 'fens.me',
  'ResponseGroup': 'History'
}, function (err, res) {
    if(err) console.log(err);
    console.log(res.trafficHistory);
    console.log(res.trafficHistory.range);
    console.log(res.trafficHistory.site);
    console.log(res.trafficHistory.start);
    console.log(res.trafficHistory.historicalData);
    console.log(res.trafficHistory.historicalData.data);
    console.log(res.trafficHistory.historicalData.data.length);
    res.trafficHistory.historicalData.data.forEach(function (item) {
      console.log(item.date);
      console.log(item.pageViews);
      console.log(item.rank);
      console.log(item.reach);
    });
});

运行程序


~ D:\workspace\nodejs\nodejs-alexa>node alexa.js
=============TrafficHistory=================
{ range: '31',
  site: 'fens.me',
  start: '2015-09-23',
  historicalData:
   { data:
      [ [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object] ] } }

// 省略输出

SitesLinkingIn接口


console.log("=============SitesLinkingIn=================");
client({
  'Action': 'SitesLinkingIn',
  'Url': 'fens.me',
  'ResponseGroup': 'SitesLinkingIn'
}, function (err, data) {
  if(err) console.log(err);
  console.log(data);
});

运行程序


~ D:\workspace\nodejs\nodejs-alexa>node alexa.js
=============SitesLinkingIn=================
{ sitesLinkingIn:
   { site:
      [ [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object] ] } }

CategoryBrowse接口


console.log("=============CategoryBrowse=================");
client({
  'Action': 'CategoryBrowse',
  'Url': 'fens.me',
  'Path': 'Top/china',
  'ResponseGroup': 'LanguageCategories'
}, function (err, data) {
  if(err) console.log(err);
  console.log(data);
});

运行程序


~ D:\workspace\nodejs\nodejs-alexa>node alexa.js
=============CategoryBrowse=================
{ categoryBrowse: { languageCategories: '' } }

最后,我们只需要把这个程序用web封装一下,就可以提供对用户的服务了,参考我的网站 http://fens.me/alexa

本文对应的代码请通过github进行下载,下载地址为:https://github.com/bsspirit/nodejs-alexa

Alexa网站排名以第三方的视角给全球的每个网站进行了排名,甚至是定价。做为一个优秀的网长,我们要使用好Alexa工具,了解自己的网站和竞争对手的网站,才能网站脱颖而出,成为成功的站长!

转载请注明出处:
http://blog.fens.me/nodejs-alexa/

打赏作者