

# 教程：在 JupyterLab 中设置 Jupyter notebook 以测试和调试 ETL 脚本
<a name="dev-endpoint-tutorial-local-jupyter"></a>

在本教程中，您要将 JupyterLab 中运行在本地计算机上的 Jupyter notebook 连接到开发终端节点。执行此操作是为了在部署脚本之前，以交互方式运行、调试和测试 AWS Glue 提取、转换和加载（ETL）脚本。本教程使用 Secure Shell（SSH）端口转发将本地计算机连接到 AWS Glue 开发终端节点。有关更多信息，请参阅 Wikipedia 上的[端口转发](https://en.wikipedia.org/wiki/Port_forwarding)。

## 步骤 1：安装 JupyterLab 和 Sparkmagic
<a name="dev-endpoint-tutorial-local-jupyter-install"></a>

您可以使用 `conda` 或者 `pip` 安装 JupyterLab。`conda` 是一个开源程序包管理系统和环境管理系统，在 Windows、macOS 和 Linux 上运行。`pip` 是 Python 的软件包安装程序。

如果您在 macOS 上安装，则必须先安装 Xcode，然后才能安装 Sparkmagic。

1. 安装 JupyterLab、Sparkmagic 和相关扩展。

   ```
   $ conda install -c conda-forge jupyterlab
   $ pip install sparkmagic
   $ jupyter nbextension enable --py --sys-prefix widgetsnbextension
   $ jupyter labextension install @jupyter-widgets/jupyterlab-manager
   ```

1. 检查 `sparkmagic` 的 `Location` 目录。

   ```
   $ pip show sparkmagic | grep Location
   Location: /Users/username/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages
   ```

1. 将您的目录更改为 `Location` 返回的目录，并安装 Scala 和 PySpark 的内核。

   ```
   $ cd /Users/username/.pyenv/versions/anaconda3-5.3.1/lib/python3.7/site-packages
   $ jupyter-kernelspec install sparkmagic/kernels/sparkkernel
   $ jupyter-kernelspec install sparkmagic/kernels/pysparkkernel
   ```

1. 下载示例 `config` 文件。

   ```
   $ curl -o ~/.sparkmagic/config.json https://raw.githubusercontent.com/jupyter-incubator/sparkmagic/master/sparkmagic/example_config.json
   ```

   在此配置文件中，您可以配置与 Spark 相关的参数，如 `driverMemory` 和 `executorCores`。

## 步骤 2：启动 JupyterLab
<a name="dev-endpoint-tutorial-local-jupyter-start"></a>

启动 JupyterLab 时，默认的 Web 浏览器会自动打开，显示 URL `http://localhost:8888/lab/workspaces/{workspace_name}`。

```
$ jupyter lab
```

## 步骤 3：启动 SSH 端口转发以连接您的开发终端节点
<a name="dev-endpoint-tutorial-local-jupyter-port-forward"></a>

接下来，使用 SSH 本地端口转发将本地端口（此处为 `8998`）转发到由 AWS Glue（`169.254.76.1:8998`）定义的远程目标。

1. 打开让您能够访问 SSH 的单独终端窗口。在 Microsoft Windows 中，您可以使用 [Git for Windows](https://git-scm.com/downloads) 提供的 BASH Shell，或者安装 [Cygwin](https://www.cygwin.com/)。

1. 运行以下 SSH 命令，按如下所示进行修改：
   + 将 `private-key-file-path` 替换为包含与您用于创建开发终端节点的公有密钥对应的私有密钥的 `.pem` 文件的路径。
   + 如果您正在转发 `8998` 以外的其他端口，请将 `8998` 替换为您实际在本地使用的端口号。地址 `169.254.76.1:8998` 是远程端口，您无法更改。
   + 将 `dev-endpoint-public-dns` 替换为您的开发终端节点的公有 DNS 地址。要查找此地址，请导航到您在 AWS Glue 控制台中的开发终端节点，选择所需名称，并复制在 **Endpoint details (终端节点详细信息)** 页面中列出的 **Public address (公有地址)**。

   ```
   ssh -i private-key-file-path -NTL 8998:169.254.76.1:8998 glue@dev-endpoint-public-dns
   ```

   您可能会看到类似如下的警告消息：

   ```
   The authenticity of host 'ec2-xx-xxx-xxx-xx.us-west-2.compute.amazonaws.com (xx.xxx.xxx.xx)'
   can't be established.  ECDSA key fingerprint is SHA256:4e97875Brt+1wKzRko+JflSnp21X7aTP3BcFnHYLEts.
   Are you sure you want to continue connecting (yes/no)?
   ```

   输入 **yes**，在使用 JupyterLab 时保持终端窗口打开。

1. 检查 SSH 端口转发是否与开发终端节点正确配合使用。

   ```
   $ curl localhost:8998/sessions
   {"from":0,"total":0,"sessions":[]}
   ```

## 步骤 4：在笔记本段落中运行简单脚本片段
<a name="dev-endpoint-tutorial-local-jupyter-list-schema"></a>

现在，您在 JupyterLab 中的笔记本应该与您的开发终端节点配合使用。在笔记本中输入以下脚本片段并运行它。

1. 检查 Spark 是否成功运行。以下命令指示 Spark 计算 `1`，然后打印值。

   ```
   spark.sql("select 1").show()
   ```

1. 检查 AWS Glue Data Catalog 集成是否正常工作。以下命令可列出数据目录中的表。

   ```
   spark.sql("show tables").show()
   ```

1. 检查使用 AWS Glue 库的简单脚本片段是否有效。

   下面的脚本使用 AWS Glue Data Catalog 中的 `persons_json` 表元数据从您的示例数据中创建 `DynamicFrame`。然后，它会打印出该数据的项目计数和架构。

```
import sys
from pyspark.context import SparkContext
from awsglue.context import GlueContext
 
# Create a Glue context
glueContext = GlueContext(SparkContext.getOrCreate())
 
# Create a DynamicFrame using the 'persons_json' table
persons_DyF = glueContext.create_dynamic_frame.from_catalog(database="legislators", table_name="persons_json")
 
# Print out information about *this* data
print("Count:  ", persons_DyF.count())
persons_DyF.printSchema()
```

脚本的输出如下所示。

```
 Count:  1961
 root
 |-- family_name: string
 |-- name: string
 |-- links: array
 |    |-- element: struct
 |    |    |-- note: string
 |    |    |-- url: string
 |-- gender: string
 |-- image: string
 |-- identifiers: array
 |    |-- element: struct
 |    |    |-- scheme: string
 |    |    |-- identifier: string
 |-- other_names: array
 |    |-- element: struct
 |    |    |-- note: string
 |    |    |-- name: string
 |    |    |-- lang: string
 |-- sort_name: string
 |-- images: array
 |    |-- element: struct
 |    |    |-- url: string
 |-- given_name: string
 |-- birth_date: string
 |-- id: string
 |-- contact_details: array
 |    |-- element: struct
 |    |    |-- type: string
 |    |    |-- value: string
 |-- death_date: string
```

## 问题排查
<a name="dev-endpoint-tutorial-local-jupyter-troubleshooting"></a>
+ 在 JupyterLab 安装过程中，如果您的计算机位于公司代理或防火墙后面，您可能会遇到由公司 IT 部门管理的自定义安全配置文件造成的 HTTP 和 SSL 错误。

  以下是当 `conda` 无法连接到其自己的存储库时的一个典型错误示例：

  ```
  CondaHTTPError: HTTP 000 CONNECTION FAILED for url <https://repo.anaconda.com/pkgs/main/win-64/current_repodata.json>
  ```

  发生这种情况可能是因为您的公司可能阻止与 Python 和 JavaScript 社区中广泛使用的存储库的连接。有关更多信息，请参阅 JupyterLab 网站上的[安装问题](https://jupyterlab.readthedocs.io/en/stable/getting_started/installation.html#installation-problems)。
+ 如果您在尝试连接到开发终端节点时遇到*连接被拒绝*错误，说明您可能正在使用过期的开发终端节点。尝试创建新的开发终端节点并重新连接。