以下内容假使读者已具备正确上网技能,如果不能正确上网部分链接会无法打开。

1. 安装 Homebrew

Homebrew 是包管理工具,也可安装管理 GUI 软件,第一件事就是打开 term.app 安装 Homebrew,安装命令直接复制自官网

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

2. 通过 Homebrew 安装 iTerm2

iTerm2 相比自带的终端拥有更多功能以及更好用的分屏

brew install iterm2

2.1 配置 iTerm2

配置支持 ⌘ ← , ⌘ →, ⌥ ←, ⌥ → 快捷键在终端中快速调整单词

快捷键.

3. 安装 Oh My Zsh

sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

4. 配置 .zshrc

4.1 增加 zsh 插件

编辑 ~/.zshrc

vi ~/.zshrc

修改 plugins 部分增加插件 z, zsh-autosuggestions, zsh-syntax-highlighting

plugins=(git z zsh-autosuggestions zsh-syntax-highlighting)

其中 zsh-autosuggestions, zsh-syntax-highlighting 需要用以下命令下载

git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

4.2 去除用户名显示

编辑 ~/.zshrc

vi ~/.zshrc

加入以下内容

# User configuration
export DEFAULT_USER="$(whoami)"

4.3 增加快捷命令

编辑 ~/.zshrc

vi ~/.zshrc

加入以下内容

alias proxy='export https_proxy=http://127.0.0.1:8888;export http_proxy=http://127.0.0.1:8888;export all_proxy=socks5://127.0.0.1:8889'
alias unproxy='unset https_proxy http_proxy all_proxy'

4.4 安装 Powerline 字体

如果额外设置了主题带有特殊字体可能需要再安装 Powerline 字体

cd ~/Developer

git clone https://github.com/powerline/fonts.git  # 将 Powerline 字体文件下载到「下载」文件夹中

cd fonts && ./install.sh  # 安装所有 Powerline 字体

安装好之后按 ⌘, 打开终端偏好设置,在描述文件 > 文本中更改字体。

5. 安装 nvm 和 Node.js

通过 nvm 安装 Node.js 可以方便的进行版本切换

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
nvm install --lts
nvm use node

6. 安装一些 Node.js 全局依赖

npm i -g serve @vue/cli

7. 使用 Homebrew 安装需要的软件

这部分大家可以自己选择安装,安装自己需要的软件即可

brew install nginx thefuck
brew install alfred sizeup caffeine google-chrome notion teamviewer charles obs visual-studio-code firefox istat-menus postman vlc gas-mask macdown spotify cheatsheet

Reference

Apache ECharts 官方提供了在微信小程序中使用Echarts 的代码实例和 ec-canvas 组件,但是未发布 npm 包。

此项目在官方代码之上修改支持 ec-canvas 组件传入 echarts 可支持 npm 引入 echarts 或本地自定义构建后的 echarts,更符合 Web 开发体验。

并且发布 npm 包,支持小程序通过 npm 安装使用。并支持 Taro 按需引入 echarts 减小打包体积。

安装

npm install echarts-for-weixin

小程序引用

参考代码 tools/demo

  1. 首先在页面的 json 文件加入 usingComponents 配置字段
{
  "usingComponents": {
    "ec-canvas": "echarts-for-weixin"
  }
}
  1. 项目根目录创建 package.json 并执行 npm install 安装依赖
{
  "dependencies": {
    "echarts": "^5.1.2",
    "echarts-for-weixin": "^1.0.0"
  }
}
  1. 小程序开发者工具中构建 npm

点击开发者工具中的菜单栏:工具 –> 构建 npm

构建 npm
  1. 在页面中引入 echarts,可以从 npm 引入 echarts,也可以引入本地自定义构建的 echarts 以减小体积
import * as echarts from 'echarts' // 从 npm 引入 echarts
import * as echarts from './echarts' // 或者从本地引入自定义构建的 echarts
  1. 然后可以在对应页面的 wxml 中直接使用该组件
<view class="container">
  <ec-canvas id="mychart-dom-bar" canvas-id="mychart-bar" echarts="" ec=""></ec-canvas>
</view>
  1. ec-canvas 的具体用法和如何初始化图表请参考 Echarts 官方小程序示例
示例代码 ```js import * as echarts from 'echarts' let chart = null; function initChart(canvas, width, height, dpr) { chart = echarts.init(canvas, null, { width: width, height: height, devicePixelRatio: dpr // new }); canvas.setChart(chart); var option = { tooltip: { trigger: 'axis', axisPointer: { // 坐标轴指示器,坐标轴触发有效 type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' }, confine: true }, legend: { data: ['热度', '正面', '负面'] }, grid: { left: 20, right: 20, bottom: 15, top: 40, containLabel: true }, xAxis: [ { type: 'value', axisLine: { lineStyle: { color: '#999' } }, axisLabel: { color: '#666' } } ], yAxis: [ { type: 'category', axisTick: { show: false }, data: ['汽车之家', '今日头条', '百度贴吧', '一点资讯', '微信', '微博', '知乎'], axisLine: { lineStyle: { color: '#999' } }, axisLabel: { color: '#666' } } ], series: [ { name: '热度', type: 'bar', label: { normal: { show: true, position: 'inside' } }, data: [300, 270, 340, 344, 300, 320, 310], itemStyle: { // emphasis: { // color: '#37a2da' // } } }, { name: '正面', type: 'bar', stack: '总量', label: { normal: { show: true } }, data: [120, 102, 141, 174, 190, 250, 220], itemStyle: { // emphasis: { // color: '#32c5e9' // } } }, { name: '负面', type: 'bar', stack: '总量', label: { normal: { show: true, position: 'left' } }, data: [-20, -32, -21, -34, -90, -130, -110], itemStyle: { // emphasis: { // color: '#67e0e3' // } } } ] }; chart.setOption(option); return chart; } Page({ data: { echarts, ec: { onInit: initChart } }, onReady() { setTimeout(function () { // 获取 chart 实例的方式 console.log(chart) }, 2000); } }) ```

Taro 引用

参考代码 examples/taro

准备工作

  1. 安装依赖
npm install echarts-for-weixin
  1. 在项目根目录中新建文件 project.package.json 或者自定义命名,此文件是小程序的 package.json,并在下一步中添加小程序自定义构建 npm 方式。这么做的目的是为了能够共享项目 node_modules

project.package.json

{
  "dependencies": {
    "echarts": "^5.1.2",
    "echarts-for-weixin": "^1.0.2"
  }
}
  1. project.configsetting 中添加小程序自定义构建 npm 方式,参考 自定义 node_modules 和 miniprogram_npm 位置的构建 npm 方式
{
  "setting": {
    "packNpmManually": true,
    "packNpmRelationList": [
      {
        "packageJsonPath": "../project.package.json",
        "miniprogramNpmDistDir": "./"
      }
    ]
  }
}
  1. 执行 Taro 的开发或者打包命令进行项目开发
npm run dev:weapp
  1. 小程序开发者工具中构建 npm。注意:小程序开发工具打开的项目目录是 dist 文件夹

点击开发者工具中的菜单栏:工具 –> 构建 npm

构建 npm

引入 Echarts

  1. 在全局的 app.config.js 中添加或者在单个需要使用到 echarts 的页面配置中添加引用组件
{
  "usingComponents": {
    "ec-canvas": "echarts-for-weixin"
  }
}
  1. 在页面中引入 echarts,可以从 npm 引入 echarts,也可以引入本地自定义构建的 echarts 以减小体积
import * as echarts from 'echarts' // 从 npm 引入 echarts
import * as echarts from './echarts' // 或者从本地引入自定义构建的 echarts
  1. 将引入的 echarts 传给组件
<ec-canvas 
  id='mychart-dom-area' 
  canvas-id='mychart-area' 
  echarts={echarts} // 将引入的 echarts 传给组件
  ec={this.state.ec}
/>
  1. ec-canvas 的具体用法和如何初始化图表请参考 Echarts 官方小程序示例
示例代码 ```js function initChart(canvas, width, height) { const chart = echarts.init(canvas, null, { width: width, height: height }) canvas.setChart(chart) const model = { yCates: ['Saturday', 'Friday', 'Thursday', 'Wednesday', 'Tuesday', 'Monday', 'Sunday'], xCates: ['1', '2', '3', '4', '5'], data: [ // [yCateIndex, xCateIndex, value] [0, 0, 5], [0, 1, 7], [0, 2, 3], [0, 3, 5], [0, 4, 2], [1, 0, 1], [1, 1, 2], [1, 2, 4], [1, 3, 8], [1, 4, 2], [2, 0, 2], [2, 1, 3], [2, 2, 8], [2, 3, 6], [2, 4, 7], [3, 0, 3], [3, 1, 7], [3, 2, 5], [3, 3, 1], [3, 4, 6], [4, 0, 3], [4, 1, 2], [4, 2, 7], [4, 3, 8], [4, 4, 9], [5, 0, 2], [5, 1, 2], [5, 2, 3], [5, 3, 4], [5, 4, 7], [6, 0, 6], [6, 1, 5], [6, 2, 3], [6, 3, 1], [6, 4, 2] ] } const data = model.data.map(function (item) { return [item[1], item[0], item[2] || '-'] }) const option = { tooltip: { position: 'top' }, animation: false, grid: { bottom: 60, top: 10, left: 80 }, xAxis: { type: 'category', data: model.xCates }, yAxis: { type: 'category', data: model.yCates }, visualMap: { min: 1, max: 10, show: false, calculable: true, orient: 'horizontal', left: 'center', bottom: 10, inRange: { color: ['#37A2DA', '#32C5E9', '#67E0E3', '#91F2DE', '#FFDB5C', '#FF9F7F'], } }, series: [{ name: 'Punch Card', type: 'heatmap', data: data, label: { normal: { show: true } }, itemStyle: { emphasis: { shadowBlur: 10, shadowColor: 'rgba(0, 0, 0, 0.5)' } } }] } chart.setOption(option) return chart } export default class Echarts extends React.Component { state = { ec: { onInit: initChart } } render () { return ( <ec-canvas id='mychart-dom-area' canvas-id='mychart-area' echarts={echarts} ec={this.state.ec} /> ) } } ```

Taro 按需引用

参考代码 examples/taro-manual-load

注意:小程序开发者工具打开的项目目录是打包后的 dist 目录

准备工作

  1. 安装依赖
npm install echarts-for-weixin
  1. 在项目根目录中新建文件 project.package.json 或者自定义命名,此文件是小程序的 package.json,并在下一步中添加小程序自定义构建 npm 方式。并配置 config/index.js 中的 copy 选项,将 project.package.json 复制到 dist 目录下并且重命名为 package.json。并且复制 node_modules/echarts-for-weixindist/node_modules/echarts-for-weixin 避免在小程序开发者工具中打开的项目重新安装依赖

project.package.json

{
  "dependencies": {
    "echarts-for-weixin": "^1.0.2"
  }
}

config/index.js

{
  copy: {
    patterns: [
      { from: 'project.package.json', to: 'dist/package.json' }, // 指定需要 copy 的文件
      { from: 'node_modules/echarts-for-weixin/', to: 'dist/node_modules/echarts-for-weixin/' }
    ],
    options: {}
  }
}
  1. project.configsetting 中添加小程序自定义构建 npm 方式,参考 自定义 node_modules 和 miniprogram_npm 位置的构建 npm 方式
{
  "setting": {
    "packNpmManually": true,
    "packNpmRelationList": [
      {
        "packageJsonPath": "./package.json",
        "miniprogramNpmDistDir": "./"
      }
    ]
  }
}
  1. 执行 Taro 的开发或者打包命令进行项目开发
npm run dev:weapp
  1. 小程序开发者工具中构建 npm。注意:小程序开发工具打开的项目目录是 dist 文件夹

点击开发者工具中的菜单栏:工具 –> 构建 npm

构建 npm

引入 Echarts

  1. 在全局的 app.config.js 中添加或者在单个需要使用到 echarts 的页面配置中添加引用组件
{
  "usingComponents": {
    "ec-canvas": "echarts-for-weixin"
  }
}
  1. 在页面中引入 echarts/core 和需要的组件,Taro 打包会只打包引入的组件,这样达到按需引入的目的
// Import the echarts core module, which provides the necessary interfaces for using echarts.
import * as echarts from 'echarts/core';
// Import charts, all with Chart suffix
import {
  // LineChart,
  BarChart,
  // PieChart,
  // ScatterChart,
  // RadarChart,
  // MapChart,
  // TreeChart,
  // TreemapChart,
  // GraphChart,
  // GaugeChart,
  // FunnelChart,
  // ParallelChart,
  // SankeyChart,
  // BoxplotChart,
  // CandlestickChart,
  // EffectScatterChart,
  // LinesChart,
  // HeatmapChart,
  // PictorialBarChart,
  // ThemeRiverChart,
  // SunburstChart,
  // CustomChart,
} from 'echarts/charts';
// import components, all suffixed with Component
import {
  // GridSimpleComponent,
  GridComponent,
  // PolarComponent,
  // RadarComponent,
  // GeoComponent,
  // SingleAxisComponent,
  // ParallelComponent,
  // CalendarComponent,
  // GraphicComponent,
  // ToolboxComponent,
  TooltipComponent,
  // AxisPointerComponent,
  // BrushComponent,
  TitleComponent,
  // TimelineComponent,
  // MarkPointComponent,
  // MarkLineComponent,
  // MarkAreaComponent,
  // LegendComponent,
  // LegendScrollComponent,
  // LegendPlainComponent,
  // DataZoomComponent,
  // DataZoomInsideComponent,
  // DataZoomSliderComponent,
  // VisualMapComponent,
  // VisualMapContinuousComponent,
  // VisualMapPiecewiseComponent,
  // AriaComponent,
  // TransformComponent,
  DatasetComponent,
} from 'echarts/components';
// Import renderer, note that introducing the CanvasRenderer or SVGRenderer is a required step
import {
  CanvasRenderer,
  // SVGRenderer,
} from 'echarts/renderers';
// Register the required components
echarts.use(
  [
    TitleComponent,
    TooltipComponent, 
    GridComponent, 
    BarChart, 
    CanvasRenderer, 
    HeatmapChart, 
    VisualMapComponent,
    VisualMapContinuousComponent,
    VisualMapPiecewiseComponent,
  ]
);
  1. 将引入的 echarts 传给组件
<ec-canvas 
  id='mychart-dom-area' 
  canvas-id='mychart-area' 
  echarts={echarts} // 将引入的 echarts 传给组件
  ec={this.state.ec}
/>
  1. ec-canvas 的具体用法和如何初始化图表请参考 Echarts 官方小程序示例
示例代码 ```js function initChart(canvas, width, height) { const chart = echarts.init(canvas, null, { width: width, height: height }) canvas.setChart(chart) const model = { yCates: ['Saturday', 'Friday', 'Thursday', 'Wednesday', 'Tuesday', 'Monday', 'Sunday'], xCates: ['1', '2', '3', '4', '5'], data: [ // [yCateIndex, xCateIndex, value] [0, 0, 5], [0, 1, 7], [0, 2, 3], [0, 3, 5], [0, 4, 2], [1, 0, 1], [1, 1, 2], [1, 2, 4], [1, 3, 8], [1, 4, 2], [2, 0, 2], [2, 1, 3], [2, 2, 8], [2, 3, 6], [2, 4, 7], [3, 0, 3], [3, 1, 7], [3, 2, 5], [3, 3, 1], [3, 4, 6], [4, 0, 3], [4, 1, 2], [4, 2, 7], [4, 3, 8], [4, 4, 9], [5, 0, 2], [5, 1, 2], [5, 2, 3], [5, 3, 4], [5, 4, 7], [6, 0, 6], [6, 1, 5], [6, 2, 3], [6, 3, 1], [6, 4, 2] ] } const data = model.data.map(function (item) { return [item[1], item[0], item[2] || '-'] }) const option = { tooltip: { position: 'top' }, animation: false, grid: { bottom: 60, top: 10, left: 80 }, xAxis: { type: 'category', data: model.xCates }, yAxis: { type: 'category', data: model.yCates }, visualMap: { min: 1, max: 10, show: false, calculable: true, orient: 'horizontal', left: 'center', bottom: 10, inRange: { color: ['#37A2DA', '#32C5E9', '#67E0E3', '#91F2DE', '#FFDB5C', '#FF9F7F'], } }, series: [{ name: 'Punch Card', type: 'heatmap', data: data, label: { normal: { show: true } }, itemStyle: { emphasis: { shadowBlur: 10, shadowColor: 'rgba(0, 0, 0, 0.5)' } } }] } chart.setOption(option) return chart } export default class Echarts extends React.Component { state = { ec: { onInit: initChart } } render () { return ( <ec-canvas id='mychart-dom-area' canvas-id='mychart-area' echarts={echarts} ec={this.state.ec} /> ) } } ```
  1. 可以查看小程序开发者工具中的依赖分析,确定文件大小以及是否正确按需引入
按需引入

参考链接

前提

项目上线之后,线上问题尤其是线上报错导致的页面无法正常渲染是非常严重的问题。一个异常监控服务可以及时报警通知、提供有效信息和报错堆栈等排查问题。调研了部分异常监控服务以及自研成本之后,决定选择自行搭建 Sentry 这款异常监控服务。Sentry 提供 SaaS 服务也提供自行搭建部署,并且搭建部署也是非常简单方便,在功能使用上面也非常全面易用、支持多平台。

市面上也还有其他优秀的异常监控服务 阿里云 ARMS, 岳鹰, 腾讯 Badjs, Fundebug, FrontJS 等等等等

准备

  1. 一台服务器,由于运行了 kafka, zookeeper 等等服务并且如果后续接入业务流量较大还是需要一定配置,建议服务器规格至少 4G 内存,条件运行可以 8G 内存,官方文档中说明至少需要 2400MB RAM 。这里使用的是 Google Cloud 上的 n1-standard-1 (1 vCPU, 3.75 GB memory) 搭配 CentOS 7 演示,在公司内部搭建的是阿里云的服务器。
  2. 一个可以提供 smtp 端口发邮件的邮箱,由于用户注册、报警通知等都会通过发送邮件所以邮箱还是近乎必须的
  3. 部分 git, shell, docker 的知识

Docker

Sentry On-Premise 的安装脚本使用 DockerDocker Compose, 可以很方便的搭建起来。所以我们先在服务器上搭建 Docker

以下命令都在 root 用户下操作,这里先切换成超级用户

sudo -i

参考 Docker 文档安装 docker,如果需要安装特定版本或者不同操作系统,官方文档都提供了不同的安装方法可以参考阅读

# 安装 yum-utils
yum install -y yum-utils

# 添加 docker 官方仓库
yum-config-manager \
  --add-repo \
  https://download.docker.com/linux/centos/docker-ce.repo

# 安装最新版的 docker
yum install docker-ce docker-ce-cli containerd.io

# 启动 docker
systemctl start docker

# 测试 docker 是否安装成功
docker run hello-world

还需要 docker-compose 所以也参考官方文档安装,如果国内服务器连接 Github 速度较慢可以使用一些国内的镜像

# 从 github 上下载 docker-compose
curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

# 使 docker-compose 可执行
chmod +x /usr/local/bin/docker-compose

# 添加软链方便使用
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

# 运行下确认版本及安装成功
docker-compose --version

部署 Sentry

安装 Git 来克隆项目

yum install git

克隆项目,切换到对应版本分支,master 分支为开发分支并不稳定建议切换为对应版本分支,自从 10.0.x 之后 Sentry 的版本规则从 SemVer 切换到了 CalVer

mkdir /home/admin
cd /home/admin
git clone https://github.com/getsentry/onpremise.git
cd onpremise
git checkout releases/20.0.8

克隆完项目之后,我们需要修改一些配置再执行安装脚本,比如配置发送邮件的邮箱,配置额外的插件(如钉钉推送等)

下面是克隆下来的项目目录

├── .craft.yml
├── .env # 环境参数
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── cron
│   ├── Dockerfile
│   └── entrypoint.sh
├── docker-compose.yml # docker-compose 文件
├── install.sh # 安装脚本
├── nginx # nginx 配置
│   └── nginx.conf
├── relay
│   └── config.example.yml
├── scripts
│   └── bump-version.sh
├── sentry # sentry 的自定义配置,如邮箱配置、额外插件等等
│   ├── .dockerignore
│   ├── Dockerfile
│   ├── config.example.yml
│   ├── requirements.example.txt
│   └── sentry.conf.example.py
├── symbolicator
│   └── config.example.yml
├── test.sh
└── zookeeper
    └── snapshot.0

复制一份 config.example.ymlconfig.yml 修改邮箱配置

cp sentry/config.example.yml sentry/config.yml

如果你的服务器支持 25 端口的邮箱发送,并且不打算使用加密协议 TLS 或者 SSL 发送邮件可以直接修改下面相应的配置 25 端口即可。这里使用的是阿里云的邮箱,也可以使用其他任意邮箱服务提供商。

sentry/config.yml

#mail.backend: "smtp" # Use dummy if you want to disable email entirely
mail.host: "smtp.aliyun.com"
mail.port: 25
mail.username: "youremail@aliyun.com"
mail.password: "yourpassword"
mail.use-tls: false
# The email address to send on behalf of
mail.from: "youremail@aliyun.com"

由于 Google Cloud 上的服务器禁止25 端口发送邮件,所以我们需要额外配置使用 TLS 并且使用端口 465

先复制一份 requirements.example.txtrequirements.txt 加两个插件,支持 TLS 发送邮件以及钉钉通知插件

cp sentry/requirements.example.txt sentry/requirements.txt

sentry/requirements.txt

# Add plugins here
sentry-dingtalk-new
django-smtp-ssl~=1.0

sentry/config.yml

mail.backend: "django_smtp_ssl.SSLEmailBackend" # Use dummy if you want to disable email entirely
mail.host: "smtp@aliyun.com"
mail.port: 465
mail.username: "youremail@aliyun.com"
mail.password: "yourpassword"
mail.use-tls: true
# The email address to send on behalf of
mail.from: "youremail@aliyun.com"

如果还需要其他额外配置可以单独修改对应配置。比如 nginx 的配置在 10.0.x 的版本可能上传文件的最大大小是比较小的需要修改以下

配置好后就可以执行安装脚本

./install.sh

等待安装脚本执行完成没有问题会提示以下信息

----------------
You're all done! Run the following command to get Sentry running:

  docker-compose up -d

执行 docker-compose up -d 启动服务并且打开 9000 端口访问 🎉

主界面.

服务器的出入站规则记得开放 9000 端口访问。后续也可以单独配置域名,和 https 证书,或者这部分由运维同学负责

Sentry 日常维护、日志查看

# 查看当前运行的容器列表
docker ps

# 查看镜像列表
docker image ls

# 查看各个容器的状态,CPU、内存占用等
docker stats

# 查看 docker-compose 对应的容器状态
docker-compose ps

# 查看日志
docker-compose logs -f

# 停止服务
docker-compose down

# 启动服务
docker-compose up -d

# 查看系统内存占用
free -m

# 查看进程和系统状态
top

常见问题

Q. 搭建成功之后邮件发送失败

A. 可以看下 config.yml 里的邮箱配置是否正确,服务器的 25 或者 465 端口是否开开放。可以登录之后在系统管理目录下 manage/status/mail/ 发送测试邮件。修改配置之后重新执行 ./install.sh 后会重新打包镜像即可

Q. 如何修改语言

A. 在用户设置目录下 settings/account/details/, 还可以修改时区

不同平台接入异常监控 Sentry SDK

接入 SDK 这个再单独写成文章。或者也可以参考接入文档

Reference

前提

这是一篇最近尝试使用 AWS 的 12 个月免费额度以内的 EC2 部署 Node.js 项目的实践。第一次接触服务器和线上环境部署,遇到了不少问题,很多地方都是一通 Google 之后胡乱操作出结果的。方法估计也不是最好用的,写文章主要是给自己一个总结和分享,建议可以看文末那几篇写得比我清楚很多的文章。部署 Node.js 项目还有很多其他更好的方案,比如 Digital Ocean 的 $5 一月的 VPS,新浪云的更简单的部署也可以参考之前写的文章。还有 Heroku 好像也是一个不错的解决方案,以后尝试之后再总结吧。
AWS 的 12 月免费套餐提供相当多的服务,包括最主要用到的 EC2(服务器), RDS(关系型数据库), 是一个用来搭建小型网站的很好的解决方案。详细可以参考这里
本来我以为 Elastic Beanstalk 也是包含在免费套餐里的,但是写这篇文章的时候发现并不是 XD。不然使用 Elastic Beanstalk 一键部署项目应该是更简单的选择。我也尝试过使用 Elastic Beanstalk 部署,但是代码上传完毕之后报错找不到 package.json 就不了了之了。
另外说一下 AWS 的收费机制是账单制度,也就是每个月底会根据你的使用量来进行收费,所以要注意自己的服务用量,以避免额外收费。

申请 AWS 账号

首先申请 AWS 账号需要提供信用卡,不确定是否需要双币信用卡。信用卡是为了验证用户信息以及后续产生的费用收费的。确认没问题之后可以在这里跟着向导进行注册,期间会收到英文电话提示输入验证码,信用卡验证会扣一笔 1 美元的扣款,理论上是为了验证卡片,后续会退回。
然后注意一下自己的注册区域,AWS 中国应该是最近两年才登陆国内的。我的账号似乎因为之前在美区注册过,注册了之后不能选择在国内区域建立主机。

创建 EC2 实例

创建 EC2 实例.

登入控制台,准备创建 EC2 实例之前先确认一下所在区域。我这里选择的是 Tokyo 的,因为之前在美国的一个主机 SSH 登录不上去,不确定是什么原因。如果是国内账号应该能选择北京或者宁夏区域。

创建 EC2 实例步骤

创建 EC2 实例步骤 跟着向导一步步向下就可以了,这里我选择的服务器是 Ubuntu 的,Ubuntu 系统默认用户名是 ubuntu 一会儿会用到。

为 EC2 配置入站端口

创建好之后首先要配置一下入站规则,让服务器允许 HTTP 端口。步骤以下。

配置入站端口.
  1. 前往 EC2 控制台。选择 Secruity Groups,选中刚刚创建的实例所用的规则,点击 Action,点击 Edit inbound rules(编辑入站规则)。
  2. 点击 Add Rule,在类型下拉框中选择 HTTP,默认会在端口处为你填上 80 端口。
  3. 添加自定义端口也是一样的步骤。类型中选择 Custom 就可以了。

连接 EC2 实例

接下来是连接 EC2 实例。这一步是比较重要的,毕竟连接上了才能做后续操作。打开终端开始输入命令吧。

连接 EC2 实例.
# 首先使用 chmod 命令来确保您的私有密钥文件不是公开可见的,
chmod 400 testEC2.pem 
# 连接。注意 @ 后面换成自己的实例 DNS 地址或者 IP 地址
ssh -i "testEC2.pem" ubuntu@ec2-198-51-100-1.compute-1.amazonaws.com

安装 Node.js

连接上之后就可以开始安装 Node.js 等我们需要的服务啦。这些全都是在命令行内操作的,安装方法也还有其他很多。参考

curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs

检查是否安装成功

node -v

安装 Apache + PHP + MySQL

虽然我们不需要用到 Apache,但是我们需要在本地安装 MySQL。数据库服务也可以选择 AWS 提供的 RDS 更加方便。但是我创建的 RDS 实例连不上,所以就直接在服务器上搭数据库了。 这里直接安装 LAMP, 参考

# 检查更新
sudo apt-get update
# 安装 LAMP
sudo apt-get install lamp-server^

也可以分开安装,具体就不详述了。如果需要 phpmyadmin, 参考

# 安装 phpmyadmin
sudo apt-get install phpmyadmin apache2-utils

连接数据库验证一下安装是否成功

mysql -u root -p

验证 Apach 是否安装成功直接打开 EC2 DNS地址就可以了,看到页面就说明 Apache 启动成功。如果没有看到页面,可以尝试重启 EC2 实例。

这里因为不需要 Apach 并且想偷懒直接把 Node 运行在 80 端口,所以把 Apache 禁用了

 sudo systemctl stop apache2.service.

部署

我这里部署是直接从 Github 上把自己项目 clone 下来的,这是最方便的方式了。

git clone https://github.com/yourapp.git
cd yourapp

# 执行 screen 保持 node 一直在跑。 SSH 连接过几分钟没有操作是会自动断开的
screen
# 因为 app.js 中设置了端口号为 80 所以需要 sudo 权限启动应用,否则不需要
sudo node app.js

打开 EC2 DNS地址访问是否能够看到页面。至此部署成功啦,Hooray!

绑定 Elastic IP 以及自定义域名

如果不想用系统分配的一长串的 DNS 地址或者 IP 地址来访问网站的话就需要自定义域名啦。下面说一下如何给 EC2 分配静态 IP 并且绑定自定义域名。

给 EC2 实例分配静态 IP.

为了要给 EC2 实例绑定自定义域名首先要使用 Elastic IP 给他分配静态 IP 地址。注意 AWS 规定创建了一个静态 IP 地址如果没有绑定实例是会按小时收费的。
点击 Elastic IP,点击 Allocate new address, 在弹出的窗口中将 EC2 实例(Instance)分配给这个地址。

回到 EC2 控制台可以看到实例地址也做了改变。.

到自己的域名注册商中解析域名

这里我使用的是 namecheap,其他域名提供商解析域名方式也大同小异。

添加一条 A 纪录,使用二级域名的话 Host 里填二级域名,使用主域名则添空,后面 Value 填前面 Elastic IP 分配的静态 IP 就可以了。.

参考文档

时隔多年,又重新(正式)开始学习和成为一名码农了。这个 Blog 自从架好之后过去这么多年也从来没有写过任何东西,那么以后就边纪录边学习吧!

npm start