快速入门:使用 Azure Developer CLI 创建函数并将其部署到 Azure Functions
在本快速入门中,你将使用 Azure 开发人员命令行工具创建响应 HTTP 请求的函数。 在本地测试代码后,将其部署到你创建的在 Azure Functions 的 Flex 消耗计划中运行的新无服务器函数应用中。
项目源使用 Azure Developer CLI (azd) 来简化将代码部署到 Azure 的过程。 此部署遵循安全且可缩放的 Azure Functions 部署的当前最佳做法。
默认情况下,Flex 消耗计划采用按使用量付费的计费模式,这意味着完成此快速入门只需在你的 Azure 帐户中支付几美分或更少费用。
先决条件
具有活动订阅的 Azure 帐户。 创建帐户。
- Java 17 开发人员工具包
- 如果使用另一个支持的 Java 版本,则必须更新项目的 pom.xml 文件。
JAVA_HOME
环境变量必须设置为正确版本的 JDK 的安装位置。
- Apache Maven 3.8.x
- 安全的 HTTP 测试工具 ,用于将具有 JSON 有效负载的请求发送到函数终结点。 本文使用的是
curl
。
初始化项目
可以使用 azd init
命令从模板创建本地 Azure Functions 代码项目。
在本地终端或命令提示符下,在空文件夹中运行此
azd init
命令:azd init --template functions-quickstart-dotnet-azd -e flexquickstart-dotnet
此命令从模板存储库中拉取项目文件,并在当前文件夹中初始化项目。
-e
标志设置当前环境的名称。 在azd
中,环境用于维护应用的唯一部署上下文,你可以定义多个环境。 它也在 Azure 中你创建的资源组名称中使用。运行此命令以导航到
http
应用文件夹:cd http
在包含此 JSON 数据的
http
文件夹中创建名为 local.settings.json 的文件:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated" } }
在本地运行时,需要此文件。
在本地终端或命令提示符下,在空文件夹中运行此
azd init
命令:azd init --template azure-functions-java-flex-consumption-azd -e flexquickstart-java
此命令从模板存储库中拉取项目文件,并在当前文件夹中初始化项目。
-e
标志设置当前环境的名称。 在azd
中,环境用于维护应用的唯一部署上下文,你可以定义多个环境。 它也在 Azure 中你创建的资源组名称中使用。运行此命令以导航到
http
应用文件夹:cd http
在包含此 JSON 数据的
http
文件夹中创建名为 local.settings.json 的文件:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "java" } }
在本地运行时,需要此文件。
在本地终端或命令提示符下,在空文件夹中运行此
azd init
命令:azd init --template functions-quickstart-javascript-azd -e flexquickstart-js
此命令从模板存储库中拉取项目文件,并在根文件夹中初始化项目。
-e
标志设置当前环境的名称。 在azd
中,环境用于维护应用的唯一部署上下文,你可以定义多个环境。 它也在 Azure 中你创建的资源组名称中使用。在包含此 JSON 数据的根文件夹中创建名为 local.settings.json 的文件:
{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "node" } }
在本地运行时,需要此文件。
在本地终端或命令提示符下,在空文件夹中运行此
azd init
命令:azd init --template functions-quickstart-powershell-azd -e flexquickstart-ps
此命令从模板存储库中拉取项目文件,并在根文件夹中初始化项目。
-e
标志设置当前环境的名称。 在azd
中,环境用于维护应用的唯一部署上下文,你可以定义多个环境。 它也在 Azure 中你创建的资源组名称中使用。运行此命令以导航到
src
应用文件夹:cd src
在包含此 JSON 数据的
src
文件夹中创建名为 local.settings.json 的文件:{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "powershell", "FUNCTIONS_WORKER_RUNTIME_VERSION": "7.2" } }
在本地运行时,需要此文件。
在本地终端或命令提示符下,在空文件夹中运行此
azd init
命令:azd init --template functions-quickstart-typescript-azd -e flexquickstart-ts
此命令从模板存储库中拉取项目文件,并在根文件夹中初始化项目。
-e
标志设置当前环境的名称。 在azd
中,环境用于维护应用的唯一部署上下文,你可以定义多个环境。 它也在 Azure 中你创建的资源组名称中使用。在包含此 JSON 数据的根文件夹中创建名为 local.settings.json 的文件:
{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "node" } }
在本地运行时,需要此文件。
在本地终端或命令提示符下,在空文件夹中运行此
azd init
命令:azd init --template functions-quickstart-python-http-azd -e flexquickstart-py
此命令从模板存储库中拉取项目文件,并在根文件夹中初始化项目。
-e
标志设置当前环境的名称。 在azd
中,环境用于维护应用的唯一部署上下文,你可以定义多个环境。 它也在 Azure 中你创建的资源组名称中使用。在包含此 JSON 数据的根文件夹中创建名为 local.settings.json 的文件:
{ "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "python" } }
在本地运行时,需要此文件。
创建并激活虚拟环境
在根文件夹中,运行以下命令以创建并激活一个名为 .venv
的虚拟环境:
python3 -m venv .venv
source .venv/bin/activate
如果 Python 未在 Linux 分发版中安装 venv 包,请运行以下命令:
sudo apt-get install python3-venv
在本地环境中运行
在终端或命令提示符下从应用文件夹运行以下命令:
func start
mvn clean package mvn azure-functions:run
npm install func start
npm install npm start
当 Functions 主机在本地项目文件夹中启动时,它会将 HTTP 触发函数的 URL 终结点写入终端输出。
在浏览器中,导航到
httpget
终结点,该终结点应类似于以下 URL:在新终端或命令提示符窗口中运行此
curl
命令,向httppost
终结点发送带有 JSON 有效负载的 POST 请求:curl -i http://localhost:7071/api/httppost -H "Content-Type: text/json" -d @testdata.json
curl -i http://localhost:7071/api/httppost -H "Content-Type: text/json" -d "@src/functions/testdata.json"
此命令从
testdata.json
项目文件读取 JSON 有效负载数据。 可以在test.http
项目文件中找到这两个 HTTP 请求的示例。完成后,在终端窗口中按 Ctrl+C 停止
func.exe
主机进程。
- 运行
deactivate
以关闭虚拟环境。
查看代码(可选)
可以查看定义两个 HTTP 触发器函数终结点的代码:
[Function("httpget")]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get")]
HttpRequest req,
string name)
{
var returnValue = string.IsNullOrEmpty(name)
? "Hello, World."
: $"Hello, {name}.";
_logger.LogInformation($"C# HTTP trigger function processed a request for {returnValue}.");
return new OkObjectResult(returnValue);
}
@FunctionName("httpget")
public HttpResponseMessage run(
@HttpTrigger(
name = "req",
methods = {HttpMethod.GET},
authLevel = AuthorizationLevel.FUNCTION)
HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
context.getLogger().info("Java HTTP trigger processed a request.");
// Parse query parameter
String name = Optional.ofNullable(request.getQueryParameters().get("name")).orElse("World");
return request.createResponseBuilder(HttpStatus.OK).body("Hello, " + name).build();
}
const { app } = require('@azure/functions');
app.http('httpget', {
methods: ['GET'],
authLevel: 'function',
handler: async (request, context) => {
context.log(`Http function processed request for url "${request.url}"`);
const name = request.query.get('name') || await request.text() || 'world';
return { body: `Hello, ${name}!` };
}
});
import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";
export async function httpGetFunction(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
context.log(`Http function processed request for url "${request.url}"`);
const name = request.query.get('name') || await request.text() || 'world';
return { body: `Hello, ${name}!` };
};
app.http('httpget', {
methods: ['GET'],
authLevel: 'function',
handler: httpGetFunction
});
此 function.json
文件定义 httpget
函数:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "Request",
"methods": [
"get"
],
"route": "httpget"
},
{
"type": "http",
"direction": "out",
"name": "Response"
}
]
}
此 run.ps1
文件实现函数代码:
using namespace System.Net
# Input bindings are passed in via param block.
param($Request, $TriggerMetadata)
# Write to the Azure Functions log stream.
Write-Host "PowerShell HTTP trigger function processed a request."
# Interact with query parameters
$name = $Request.Query.name
$body = "This HTTP triggered function executed successfully. Pass a name in the query string for a personalized response."
if ($name) {
$body = "Hello, $name. This HTTP triggered function executed successfully."
}
# Associate values to output bindings by calling 'Push-OutputBinding'.
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
StatusCode = [HttpStatusCode]::OK
Body = $body
})
@app.route(route="httpget", methods=["GET"])
def http_get(req: func.HttpRequest) -> func.HttpResponse:
name = req.params.get("name", "World")
logging.info(f"Processing GET request. Name: {name}")
return func.HttpResponse(f"Hello, {name}!")
可在此处查看完整的模板项目。
可在此处查看完整的模板项目。
可在此处查看完整的模板项目。
可在此处查看完整的模板项目。
可在此处查看完整的模板项目。
可在此处查看完整的模板项目。
在本地验证函数后,可以将其发布到 Azure。
创建 Azure 资源
此项目配置为使用 azd provision
命令在 Flex 消耗计划中创建函数应用,以及其他所需的 Azure 资源。
注意
该项目包括一组 Bicep 文件,azd
使用这些文件可以按照最佳做法为 Flex 消耗计划创建安全部署。
Java 应用目前不支持 azd up
和 azd deploy
命令。
在项目的根文件夹中,运行以下命令以创建所需的 Azure 资源:
azd provision
根文件夹包含
azd
所需的azure.yaml
定义文件。如果尚未登录,系统会要求你使用 Azure 帐户进行身份验证。
出现提示时,请提供以下所需的部署参数:
参数 描述 Azure 订阅 要在其中创建资源的订阅。 Azure 位置 要在其中创建包含新 Azure 资源的资源组的 Azure 区域。 仅显示当前支持 Flex 消耗计划的区域。 azd provision
命令使用你对这些提示的回复和 Bicep 配置文件来创建和配置这些所需的 Azure 资源:- Flex 消耗计划和函数应用
- Azure 存储(必需)和 Application Insights(推荐)
- 帐户的访问策略和角色
- 使用托管标识(而不是存储的连接字符串)的服务到服务连接
- 安全运行函数应用和其他 Azure 资源的虚拟网络
命令成功完成后,可以将项目代码部署到 Azure 中的这个新函数应用。
部署到 Azure
可以使用 Core Tools 打包代码,并从 target
输出文件夹将其部署到 Azure。
导航到
target
输出文件夹中等效的应用文件夹:cd http/target/azure-functions/contoso-functions
此文件夹应具有 host.json 文件,该文件指示它是已编译 Java 函数应用的根目录。
运行以下命令,使用 Core Tools 将已编译的 Java 代码项目部署到 Azure 中的新函数应用资源:
azd env get-value
命令从本地环境中获取函数应用名称,这是使用func azure functionapp publish
进行部署所必需的。 发布成功完成后,可以看到指向 Azure 中的 HTTP 触发器终结点的链接。
部署到 Azure
此项目配置为使用 azd up
命令将此项目部署到 Azure 中 Flex 消耗计划中的新函数应用。
提示
该项目包括一组 Bicep 文件,azd
使用这些文件可以按照最佳做法为 Flex 消耗计划创建安全部署。
运行以下命令,让
azd
在 Azure 中创建所需的 Azure 资源,并将代码项目部署到新的函数应用:azd up
根文件夹包含
azd
所需的azure.yaml
定义文件。如果尚未登录,系统会要求你使用 Azure 帐户进行身份验证。
出现提示时,请提供以下所需的部署参数:
参数 描述 Azure 订阅 要在其中创建资源的订阅。 Azure 位置 要在其中创建包含新 Azure 资源的资源组的 Azure 区域。 仅显示当前支持 Flex 消耗计划的区域。 azd up
命令使用你对这些提示的回复和 Bicep 配置文件来完成这些部署任务:创建和配置这些所需的 Azure 资源(等效于
azd provision
):- Flex 消耗计划和函数应用
- Azure 存储(必需)和 Application Insights(推荐)
- 帐户的访问策略和角色
- 使用托管标识(而不是存储的连接字符串)的服务到服务连接
- 安全运行函数应用和其他 Azure 资源的虚拟网络
打包代码并将其部署到部署容器(等效于
azd deploy
)。 然后,应用将启动并在已部署的包中运行。
命令成功完成后,你会看到指向所创建资源的链接。
在 Azure 上调用函数
现在,可以通过使用 HTTP 测试工具或浏览器(对于 GET 请求)向 URL 发出 HTTP 请求来调用 Azure 中的函数终结点。 函数在 Azure 中运行时,系统将强制实施访问密钥授权,你必须向请求提供函数访问密钥。
可以使用 Core Tools 获取 Azure 中运行的函数的 URL 终结点。
在本地终端或命令提示符下,运行以下命令以获取 URL 终结点值:
$APP_NAME = azd env get-value AZURE_FUNCTION_NAME func azure functionapp list-functions $APP_NAME --show-keys
azd env get-value
命令从本地环境中获取函数应用名称。 将--show-keys
选项与func azure functionapp list-functions
一起使用,意味着每个终结点返回的“Invoke URL:”值都包含一个函数级访问密钥。与之前一样,使用 HTTP 测试工具在 Azure 中运行的函数应用中验证这些 URL。
重新部署代码
可以根据需要多次运行 azd up
命令,以预配 Azure 资源并为函数应用部署代码更新。
注意
已部署的代码文件始终被最新的部署包覆盖。
对 azd
提示的初始响应和 azd
生成的任何环境变量都本地存储在你的命名环境中。 使用 azd env get-values
命令查看创建 Azure 资源时使用的环境中的所有变量。
清理资源
使用完函数应用和相关资源后,可以使用此命令从 Azure 中删除函数应用及其相关资源,并避免产生任何进一步的成本:
azd down --no-prompt
注意
--no-prompt
选项指示 azd
在未经你确认的情况下删除资源组。
此命令不会影响本地代码项目。