本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
教程:使用 Amazon OpenSearch Service 创建搜索应用程序
使用 Amazon OpenSearch Service 创建搜索应用程序的一个常用方法是使用 Web 表单将用户查询发送到服务器。然后,您可以授权服务器直接调用 OpenSearch API 并让服务器向 OpenSearch Service 发送请求。但是,如果您想编写不依赖服务器的客户端代码,则应针对安全和性能风险作出补偿。不建议允许对 OpenSearch API 的未签名公有访问权限。用户可能会访问不安全的终端节点,或者通过过于广泛的查询(或过多的查询)影响集群性能。
本章为您提供了一个解决方案:使用 Amazon API Gateway 将用户限制到一部分 OpenSearch API 和 AWS Lambda,并从 API Gateway 到 OpenSearch Service 签署请求。
注意
标准 API Gateway 和 Lambda 定价适用,但不能超出本教程的限制使用量,成本应忽略不计。
先决条件
此教程的一个先决条件是 OpenSearch Service 域。如果您还没有域,请按照创建 OpenSearch Service 域中的步骤创建一个域。
步骤 1:为示例数据建立索引
下载 sample-movies.zip,解压它,然后使用 _bulkmovies
索引:
POST https://search-my-domain
.us-west-1
.es.amazonaws.com/_bulk
{ "index": { "_index": "movies", "_id": "tt1979320" } }
{"directors":["Ron Howard"],"release_date":"2013-09-02T00:00:00Z","rating":8.3,"genres":["Action","Biography","Drama","Sport"],"image_url":"http://ia.media-imdb.com/images/M/MV5BMTQyMDE0MTY0OV5BMl5BanBnXkFtZTcwMjI2OTI0OQ@@._V1_SX400_.jpg","plot":"A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.","title":"Rush","rank":2,"running_time_secs":7380,"actors":["Daniel Brühl","Chris Hemsworth","Olivia Wilde"],"year":2013,"id":"tt1979320","type":"add"}
{ "index": { "_index": "movies", "_id": "tt1951264" } }
{"directors":["Francis Lawrence"],"release_date":"2013-11-11T00:00:00Z","genres":["Action","Adventure","Sci-Fi","Thriller"],"image_url":"http://ia.media-imdb.com/images/M/MV5BMTAyMjQ3OTAxMzNeQTJeQWpwZ15BbWU4MDU0NzA1MzAx._V1_SX400_.jpg","plot":"Katniss Everdeen and Peeta Mellark become targets of the Capitol after their victory in the 74th Hunger Games sparks a rebellion in the Districts of Panem.","title":"The Hunger Games: Catching Fire","rank":4,"running_time_secs":8760,"actors":["Jennifer Lawrence","Josh Hutcherson","Liam Hemsworth"],"year":2013,"id":"tt1951264","type":"add"}
...
请注意,上方是一个示例命令,其中包含一小部分可用数据。要执行 _bulk
操作,您需要复制和粘贴 sample-movies
文件的全部内容。有关更多说明,请参阅 选项 2:上传多个文档。
您也可以使用以下 curl 命令实现相同的结果:
curl -XPOST -u '
master-user
:master-user-password
' 'domain-endpoint/_bulk' --data-binary @bulk_movies.json -H 'Content-Type: application/json'
步骤 2:创建并部署 Lambda 函数
在 API Gateway 中创建 API 前,创建将请求传递到的 Lambda 函数。
创建 Lambda 函数
在此解决方案中,API Gateway 会将请求传递到 Lambda 函数,该函数将查询 OpenSearch Service 并返回结果:由于此示例函数使用的是外部库,您需要创建一个部署程序包并将其上传到 Lambda。
创建部署包
-
打开命令提示符并创建
my-opensearch-function
项目目录。例如,在 macOS 上,请执行以下操作:mkdir my-opensearch-function
-
导航到
my-sourcecode-function
项目目录。cd my-opensearch-function
-
复制以下 Python 示例代码的内容,并且使用名为
opensearch-lambda.py
的新文件将其保存。将您的区域和主机端点添加到文件中。import boto3 import json import requests from requests_aws4auth import AWS4Auth
region
= '' # For example, us-west-1 service = 'es' credentials = boto3.Session().get_credentials() awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)host
= '' # The OpenSearch domain endpoint with https:// and without a trailing slash index = 'movies' url = host + '/' + index + '/_search' # Lambda execution starts here def lambda_handler(event, context): # Put the user query into the query DSL for more accurate search results. # Note that certain fields are boosted (^). query = { "size": 25, "query": { "multi_match": { "query": event['queryStringParameters']['q'], "fields": ["title^4", "plot^2", "actors", "directors"] } } } # Elasticsearch 6.x requires an explicit Content-Type header headers = { "Content-Type": "application/json" } # Make the signed HTTP request r = requests.get(url, auth=awsauth, headers=headers, data=json.dumps(query)) # Create the response and add some extra content to support CORS response = { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": '*' }, "isBase64Encoded": False } # Add the search results to the response response['body'] = r.text return response -
在新的
package
目录中安装外部库。pip3 install --target ./package boto3 pip3 install --target ./package requests pip3 install --target ./package requests_aws4auth
-
使用已安装库在根目录下创建部署程序包。以下命令可在项目目录中生成
my-deployment-package.zip
文件。cd package zip -r ../my-deployment-package.zip .
-
将
opensearch-lambda.py
文件添加到 zip 文件的根目录。cd .. zip my-deployment-package.zip opensearch-lambda.py
有关创建 Lambda 函数和部署程序包的更多信息,请参阅 AWS Lambda 开发人员指南中的使用 .zip 文件归档部署 Python Lambda 函数和本指南中的 创建 Lambda 部署程序包。
使用 Lambda 控制台创建函数
-
导航到 Lambda 控制台:https://console.aws.amazon.com/lambda/home
。在左侧导航窗格中,选择函数。 -
选择创建函数。
-
配置以下字段:
-
函数名称:opensearch-function
-
运行时:Python 3.9
-
架构:x86_64
保留所有其他默认选项,然后选择创建函数。
-
-
在函数摘要页面的代码源部分,选择从下拉列表中上传,然后选择 .zip 文件。找到您创建的
my-deployment-package.zip
文件,然后选择保存。 -
处理程序是函数代码中处理事件的方法。在运行时设置下,选择编辑,根据 Lambda 函数所在的部署包中的文件名更改处理程序名称。鉴于您的文件名为
opensearch-lambda.py
,请将处理程序重命名为
。有关更多信息,请参阅 Python 中的 Lambda 函数处理程序中的。opensearch-lambda
.lambda_handler
步骤 3:在 API Gateway 中创建 API
使用 API Gateway 创建更加受限的 API 简化了与OpenSearch _search
API 交互的过程。API Gateway 还可让您启用安全功能,如 Amazon Cognito 身份验证和请求限制。执行以下步骤来创建和部署 API:
创建和配置 API
使用 API Gateway 控制台创建 API
-
通过以下网址导航到 API Gateway 控制台:https://console.aws.amazon.com/apigateway/home
。在左侧导航窗格中,选择 APIs。 -
定位REST API(非私有),然后选择构建。
-
在下一页中,找到新建 API 部分,确保选中新建 API。
-
配置以下字段:
-
API 名称:opensearch-api
-
描述:用于搜索 Amazon OpenSearch Service 域的公共 API
-
端点类型:区域
-
-
选择创建 API。
-
选择操作和创建方法。
-
在下拉菜单中选择GET,然后单击复选标记进行确认。
-
配置以下设置,然后选择保存:
设置 | 值 |
---|---|
集成类型 | Lambda 函数 |
使用 Lambda 代理集成 | 是 |
Lambda 区域 | us-west-1 |
Lambda 函数 | opensearch-lambda |
使用原定设置超时 | 是 |
配置该方法请求
选择方法请求并配置以下设置:
设置 | 值 |
---|---|
授权 | NONE |
请求验证器 |
验证查询字符串参数和标头 |
必需的 API 密钥 | false |
在 URL 查询字符串参数下,选择添加查询字符串并配置以下参数:
设置 | 值 |
---|---|
名称 | q |
必需 |
是 |
部署 API 并配置阶段
借助 API Gateway 控制台,您可以创建部署并将其与新的或现有阶段相关联,从而部署 API。
-
选择操作和部署 API。
-
对于部署阶段选择新阶段并将阶段命名为
opensearch-api-test
。 -
选择 Deploy(部署)。
-
在阶段编辑器中配置以下设置,然后选择保存更改:
设置 | 值 |
---|---|
启用限制 | 是 |
费率 |
1000 |
突增 | 500 |
这些设置将配置一个 API,该 API 只有一个方法:一个针对终端节点根的 GET
请求 (https://
)。该请求需要单个参数 (some-id
.execute-api.us-west-1
.amazonaws.com/search-es-api-testq
) - 查询字符串要搜索的。调用后,该方法会将请求传递到将运行 opensearch-lambda
函数的 Lambda。有关更多信息,请参阅在 Amazon API Gateway 中创建 API 和在 Amazon API Gateway 中部署 REST API。
步骤 4:(可选)修改域访问策略
OpenSearch Service 域必须允许 Lambda 函数向 movies
索引发出 GET
请求。如果您的域具有已启用精细访问控制的开放访问策略,则可以将其保持原样:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "es:*", "Resource": "arn:aws:es:us-west-1:123456789012:domain/
domain-name
/*" } ] }
您也可以选择建立更加精细的域访问策略。例如,以下最低策略提供了对整个 movies
索引的 opensearch-lambda-role
(通过 Lambda 创建)访问:要获取 Lambda 自动创建的角色的确切名称,请转到 AWS Identity and Access Management(IAM) 控制台,请选择角色,并搜索 “lambda”。
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:role/service-role/
opensearch-lambda-role-1abcdefg
" }, "Action": "es:ESHttpGet", "Resource": "arn:aws:es:us-west-1:123456789012:domain/domain-name
/movies/_search" } ] }
重要
如果您为域启用了精细访问控制,则还需要在 OpenSearch 控制面板中将角色映射到用户,否则就会看到权限错误。
有关访问策略的更多信息,请参阅 配置访问策略。
映射 Lambda 角色(如果使用精细访问控制)
精细访问控制将在您能测试应用程序之前引入一个额外步骤。即使您将 HTTP 基本身份验证用于所有其他目的,也需要将 Lambda 角色映射到用户,否则您将看到权限错误。
-
导航到域的 OpenSearch 控制面板 URL。
-
从主菜单中,选择安全、角色,然后选择
all_access
链接和需要将 Lambda 角色映射到的角色。 -
选择映射的用户、管理映射。
-
在 Backend roles(后端角色)下,添加 Lambda 角色的 Amazon 资源名称(ARN)。ARN 应采用
arn:aws:iam::
形式。123456789123
:role/service-role/opensearch-lambda-role-1abcdefg
-
选择映射并确认在映射的用户下显示的用户或角色。
步骤 5:测试 Web 应用程序
测试 Web 应用程序
-
下载 sample-site.zip,解压后在常用文本编辑器中打开
scripts/search.js
。 -
更新
apigatewayendpoint
变量以指向您的 API Gateway 端点,并在给定路径末尾添加反斜线。您可以选择阶段,然后选择 API 的名称,即可在 API Gateway 中快速找到端点。apigatewayendpoint
变量应采用https://
/ 形式。some-id
.execute-api.us-west-1
.amazonaws.com/opensearch-api-test -
打开
index.html
并尝试运行对 thor、house 和其他几个术语的搜索。
排除 CORS 错误
尽管 Lambda 函数在响应中包含支持 CORS 的内容,但您仍可能会看到以下错误:
Access to XMLHttpRequest at '<api-gateway-endpoint>' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present in the requested resource.
如果,请尝试以下操作:
-
在 GET 资源上启用 CORS。在 Advanced (高级) 西方,设置 Access-Control-Allow-Credentials 为
'true'
。 -
在 API Gateway 中重新部署 API (Action (操作)、Deploy API (部署 API))。
-
删除并重新添加 Lambda 函数触发器。重新添加,选择添加触发器并创建调用函数的 HTTP 端点。该触发器必须具有以下配置:
触发器 API 部署阶段 安全性 API Gateway opensearch-api opensearch-api-test 打开
后续步骤
本章只是一个展示概念的起始点。您可以考虑以下修改:
-
将您自己的数据添加到 OpenSearch Service 域。
-
将方法添加到您的 API。
-
在 Lambda 函数中,修改搜索查询或提高不同的字段。
-
以不同的方式呈现结果或修改
search.js
以向用户显示不同的字段。