应用程序间通信¶
本主题介绍一个 Snowflake Native App 可以如何利用应用程序间通信 (IAC) 与另一个 Snowflake Native App 通信。
应用程序间通信:概述¶
应用程序间通信 (IAC) 允许 Snowflake Native App 通过提供对其他应用程序可以调用的函数和过程的访问权限,在同一使用者账户中为其他 Snowflake Native Apps 提供附加功能。
例如,解析客户 IDs 的 Snowflake Native App 可以通过联接来自不同供应商的数据集,帮助其他 Snowflake Native Apps 增强客户数据。
IAC 为两个或多个独立应用程序提供相互通信的基础设施,同时尊重其管理和安全需求。应用程序开发者可以通过执行以下操作为其应用程序启用 IAC:
创建接口
使用应用程序角色控制对接口的访问。
选择同步或异步交互。同步交互使用其他应用程序可以直接调用的存储过程或函数,而异步交互提供对存储在表或视图中的请求结果的访问权限,其他应用程序可以轮询这些表或视图以查看结果。
术语¶
IAC 使用以下术语:
- 客户端
发起连接请求并调用服务器应用程序函数和过程的应用程序。
- 服务器
利用应用程序角色提供对其函数和过程的访问权限的应用程序。
- 使用者
安装客户端和服务器应用程序的用户。
- 应用程序配置
客户端应用程序用于请求服务器应用程序名称的 SQL 对象。IAC 使用
APPLICATION_NAME类型的应用程序配置来存储服务器应用程序名称。- 应用程序规范
客户端应用程序为请求连接到服务器应用程序而创建的 SQL 对象。IAC 使用
CONNECTION类型的应用程序规范。有关应用程序规范的信息,请参阅 应用程序规范概述。
应用程序间通信的工作流程¶
建立和使用连接涉及客户端应用程序和服务器应用程序之间的握手过程。
从服务器应用程序提供商处获取应用程序角色名称:客户端应用程序提供商与 Snowflake 外部的服务器应用程序提供商协调,确定在连接规范中请求哪些服务器应用程序角色。
确定目标应用程序:客户端应用程序创建一个配置定义对象,以请求服务器应用程序的名称。使用者检测传入请求,并通过配置对象向客户端应用程序提供服务器应用程序名称。
请求并批准连接:客户端应用程序创建应用程序规范以请求连接到服务器应用程序,使用者批准连接请求。
与服务器应用程序通信:客户端应用程序调用服务器应用程序的过程或函数。
确定目标应用程序¶
在客户端应用程序可以与服务器应用程序通信之前,它必须首先确定应用程序的确切名称。由于使用者可以在安装过程中为应用程序选择自定义名称,因此客户端应用程序必须首先确定服务器应用程序的确切名称。
客户端应用程序的安装脚本会创建一个 CONFIGURATION DEFINITION 对象以请求此信息。
以下示例展示了客户端应用程序的安装脚本如何创建 CONFIGURATION DEFINITION 对象来请求服务器应用程序的名称:
ALTER APPLICATION
SET CONFIGURATION DEFINITION my_server_app_name_configuration
TYPE = APPLICATION_NAME
LABEL = 'Server App'
DESCRIPTION = 'Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.'
APPLICATION_ROLES = (my_server_app_role);
以下示例展示使用者如何检查传入的配置定义请求:
SHOW CONFIGURATIONS IN APPLICATION my_server_app_name;
此命令返回的结果类似于以下内容:
name | created_on | updated_on | type | ...
my_server_app_name_configuration | 2026-02-09 10:00:00.000 | 2026-02-09 10:00:00.000 | APPLICATION_NAME | ...
然后,使用者使用以下命令提供服务器应用程序名称:
ALTER APPLICATION my_client_app_name
SET CONFIGURATION my_server_app_name_configuration
VALUE = MY_SERVER_APP_NAME;
请求并批准连接¶
一旦客户端应用程序获得了服务器应用程序的名称,它就会创建一个 APPLICATION SPECIFICATION 来请求连接到服务器应用程序。请注意,应用程序角色名称是通过 Snowflake 外部的离线通信获取的。
以下示例演示如何创建 APPLICATION SPECIFICATION 来连接到名为 my_server_app_name 的服务器应用程序:
ALTER APPLICATION SET SPECIFICATION my_server_app_name_connection_specification
TYPE = CONNECTION
LABEL = 'Server App'
DESCRIPTION = 'Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.'
SERVER_APPLICATION = MY_SERVER_APP_NAME -- server name obtained from Step 1
SERVER_APPLICATION_ROLES = (my_server_app_role);
通过创建应用程序规范,客户端应用程序请求被授予应用程序规范中指定的服务器应用程序角色。
备注
应用程序规范中给定的 LABEL 和 DESCRIPTION 值必须与在第 1 步中创建的 CONFIGURATION DEFINITION 对象中给定的 LABEL 和 DESCRIPTION 值匹配。如果值不匹配,则连接将无法在 Snowsight 中正常显示。
要创建高效的连接工作流程,我们建议客户端应用程序在 before_configuration_change 同步回调中创建应用程序规范。此回调在运行 ALTER APPLICATION SET CONFIGURATION VALUE 命令时运行。有关回调的信息,请参阅 回调。有关在 before_configuration_change 同步回调中创建应用程序规范的示例安装脚本,请参阅 示例。
客户端应用程序创建应用程序规范后,使用者可以查看并批准或拒绝连接请求。
使用 SQL 批准连接请求¶
以下示例展示了使用者如何使用 SQL 批准连接请求:
ALTER APPLICATION my_server_app_name
APPROVE SPECIFICATION my_server_app_name_connection_specification
SEQUENCE_NUMBER = 1;
使用 Snowsight 批准连接请求¶
要在 Snowsight 中查看和批准连接请求,请执行以下操作:
登录 Snowsight。
选择应用程序。标题为 Application connections 的部分显示在 Configurations 下。每个待处理的连接都会显示连接的名称或标签、连接的简要描述以及 Review 按钮。
点击 Review 按钮。此时将显示连接请求的详细信息。
从 Select from your apps 中选择目标应用程序。
点击 Next。将显示以下信息:
一个图表,显示客户端应用程序将连接到服务器应用程序,以及应用程序将使用的角色。
连接的详细信息。
将授予客户端应用程序的服务器权限的子集。有关 IAC 安全注意事项的信息,请参阅 安全注意事项。
一个 Approve Connection 切换开关。开关设置为 On。
要批准连接,请将切换开关设置为 On,然后点击 Save。更新的连接列表随即显示连接的状态。
要拒绝连接,请将切换开关切换到 Off。
要退出审查页面而不批准或拒绝连接,请点击 Cancel 按钮。
批准后¶
当使用者批准连接请求时,Snowflake Native App Framework 会将请求的服务器应用程序角色授予客户端应用程序。批准还会授予服务器应用程序对客户端应用程序的 USAGE 权限。这使服务器应用程序可以知道哪些客户端应用程序连接到它。
当使用者批准连接请求时,将分别在客户端和服务器应用程序中触发以下回调:
在客户端应用程序中触发 after_server_connection_change
在服务器应用程序中触发 after_client_connection_change
这些回调允许服务器和客户端应用程序在建立连接时执行其他操作。
有关批准应用程序规范的更多信息,请参阅以下主题:
与服务器应用程序通信¶
建立连接并授予客户端应用程序请求的服务器应用程序角色后,客户端应用程序就可以与服务器应用程序通信。
备注
在调用服务器应用程序方法之前,客户端应用程序应在运行时从批准的应用程序规范中检索服务器应用程序的名称,以确保在重命名服务器应用程序时使用正确的名称。以下示例演示如何在运行时检索服务器应用程序的名称:
SHOW APPROVED SPECIFICATIONS ->>
SELECT PARSE_JSON("definition"):"SERVER_APPLICATION"::STRING
FROM $1
WHERE "name" = 'MY_SERVER_APP_NAME_CONNECTION_SPECIFICATION';
客户端应用程序可以与服务器应用程序同步或异步通信。
同步通信涉及直接调用服务器应用程序的过程或函数。
异步通信涉及使用存储在数据对象(如表)中的队列。例如,服务器应用程序可以提供一个过程,将记录作为请求插入到表中,然后服务器应用程序会定期处理这些记录。然后,客户端应用程序可以使用服务器提供的不同过程来检查表中的结果。
以下同步操作示例展示了客户端应用程序使用 Python 调用服务器应用程序的过程:
session.call("server_app_name.customer_schema.get_customer_data", customer_id);
以下异步操作示例展示了客户端应用程序使用 Python 调用服务器应用程序的过程。客户端应用程序调用服务器应用程序的过程,该过程会在表中创建一个请求,然后由服务器应用程序处理。客户端应用程序可以轮询表,以查看结果的更新记录。
session.call("server_app_name.customer_schema.request_customer_data_async", customer_id);
然后,客户端应用程序可以轮询表,以查看结果的更新记录:
session.call("server_app_name.customer_schema.check_customer_data_requests_async", customer_id);
管理连接¶
要在 Snowsight 中查看现有连接,请执行以下操作:
登录 Snowsight。
在导航菜单中,选择 Catalog » Apps。
选择应用程序。所有应用程序连接都显示在标题为 Configurations 的部分下。在该部分下方,有一个子部分,标题为 Application connections。
要修改连接,请点击该连接的铅笔图标。您可以更改以下内容:
哪个应用程序连接到该应用程序
连接的批准状态
要查看连接的应用程序,请点击 View app 按钮。
要更改连接的安全设置,请点击齿轮图标。
安全注意事项¶
在批准规范请求时,使用者应注意,授予服务器应用程序对客户端应用程序的访问权限可能会提升客户端应用程序的权限。例如,如果服务器应用程序具有外部访问权限,则客户端应用程序可能会通过服务器应用程序间接访问互联网或其他外部资源。如果服务器应用程序是另一个服务器应用程序的客户端应用程序,则客户端应用程序可能能够通过第一个服务器应用程序访问另一个服务器应用程序的资源。
在批准连接之前,使用者应检查服务器应用程序的功能和权限。使用管理员角色(例如,ACCOUNTADMIN)来检查服务器的功能。使用权限较低的角色检查服务器不会显示服务器的所有功能和权限。使用者应注意,服务器应用程序代码对使用者不可见,并且使用者批准连接后,可以更改服务器应用程序权限和功能。
示例 SQL 命令用于检查服务器应用程序的功能和权限,包括但不限于以下命令:
SHOW GRANTS TO APPLICATION:此命令列出了已授予服务器应用程序的客户端应用程序权限。
SHOW PRIVILEGES IN APPLICATION:此命令列出了可以授予客户端应用程序的潜在账户级权限。
SHOW REFERENCES IN APPLICATION:此命令列出了客户端应用程序在不使用授权的情况下可能使用的引用。
SHOW SPECIFICATIONS IN APPLICATION:此命令列出了使用者已批准的应用程序规范,包括外部访问集成 (EAIs)、安全集成、共享、列表和连接。
SQL 参考¶
以下 SQL 命令用于管理应用程序间通信。
ALTER APPLICATION SET SPECIFICATION:选择使用 时默认使用的角色和仓库。创建一个应用程序规范,服务器应用程序使用该规范向客户端应用程序授予对其函数和过程的访问权限。
ALTER APPLICATION DROP SPECIFICATION:选择使用 时默认使用的角色和仓库。删除应用程序规范。
ALTER APPLICATION ... { APPROVE | DECLINE} SPECIFICATION:选择使用 时默认使用的角色和仓库。批准或拒绝应用程序规范请求。
SHOW SPECIFICATIONS:选择使用 时默认使用的角色和仓库。列出应用程序中的所有应用程序规范。
DESCRIBE SPECIFICATION:选择使用 时默认使用的角色和仓库。描述应用程序的应用程序规范。
ALTER APPLICATION SET CONFIGURATION DEFINITION:选择使用 时默认使用的角色和仓库。创建或更新应用程序配置(键值对),该配置向使用者请求另一个应用程序的名称。
ALTER APPLICATION DROP CONFIGURATION DEFINITION:选择使用 时默认使用的角色和仓库。删除应用程序配置。
ALTER APPLICATION SET CONFIGURATION VALUE:选择使用 时默认使用的角色和仓库。在应用程序配置中设置值。
ALTER APPLICATION UNSET CONFIGURATION:选择使用 时默认使用的角色和仓库。将值取消设置为指定的应用程序配置。
SHOW CONFIGURATIONS:选择使用 时默认使用的角色和仓库。列出应用程序中的所有应用程序配置。
DESCRIBE CONFIGURATION:选择使用 时默认使用的角色和仓库。描述应用程序配置的详细信息。
IS_CONFIGURATION_SET(SYS_CONTEXT 函数):选择使用 时默认使用的角色和仓库。返回配置是否设置了值。
GET_CONFIGURATION_VALUE(SYS_CONTEXT 函数):选择使用 时默认使用的角色和仓库。返回配置的当前值。
SHOW GRANTS TO APPLICATION:列出授予指定应用程序的所有权限和数据库/应用程序角色。
SHOW GRANTS TO APPLICATION ROLE:列出应用程序角色拥有的所有权限。
SHOW GRANTS OF APPLICATION ROLE:列出被授予指定应用程序角色的所有角色和应用程序。
回调¶
Snowflake Native App Framework 提供生命周期回调,以帮助管理应用间通信的工作流程。这些回调允许应用程序对配置、连接和规范的变更做出响应。要使用回调,请在应用的清单文件的 lifecycle_callbacks 部分中注册它们。
有关回调的一般信息,请参阅 回调。
配置回调¶
设置或取消设置配置值时会触发这些回调。一个常见的用例是使用 before_configuration_change 回调,以在使用者提供服务器应用程序名称时自动创建连接规范。
- validate_configuration_change
一个同步回调,作为
ALTER APPLICATION SET CONFIGURATION VALUE命令的一部分被调用。允许应用程序对提供的值执行自定义验证。如果回调返回错误,则命令失败,并且不会设置新值。- before_configuration_change
一个同步回调,作为
ALTER APPLICATION SET CONFIGURATION VALUE和ALTER APPLICATION UNSET CONFIGURATION命令的一部分被调用。允许应用程序在保存配置值之前根据配置值执行操作。- after_configuration_change
一个异步回调,在
ALTER APPLICATION SET CONFIGURATION VALUE或ALTER APPLICATION UNSET CONFIGURATION命令完成后被调用。允许应用程序对变更做出反应,例如出于通知或跟踪目的。
连接回调¶
当连接状态变化时,会触发这些回调,例如连接建立、被拒绝、断开,或是当连接的应用程序被删除时。
- after_server_connection_change
一个异步回调,在客户端应用程序中由任何影响连接状态的操作触发,包括批准、拒绝或删除规范,或删除服务器应用程序。
- after_client_connection_change
一个异步回调,在服务器应用程序中由任何影响连接状态的操作触发,包括批准、拒绝或删除规范,或删除客户端应用程序。
- after_server_version_change
一个异步回调,在服务器应用程序的版本或补丁号更改后,在客户端应用程序中被调用。允许客户端应用程序对升级或降级做出反应。
示例¶
以下示例演示如何配置应用程序以使用应用程序间通信。
示例:安装脚本和清单文件¶
以下示例显示了客户端应用程序的安装脚本 (setup.sql):
CREATE OR ALTER VERSIONED SCHEMA app_schema;
-- create a callback that creates the connection request before the config value of the server name is saved
CREATE OR REPLACE PROCEDURE app_schema.before_config_change_callback(config_name STRING, config_value STRING)
RETURNS STRING
LANGUAGE SQL
AS
$$
DECLARE
spec_name VARCHAR;
existing_target VARCHAR;
BEGIN
IF (config_value IS NOT NULL AND config_name = 'MY_SERVER_APP_NAME_CONFIGURATION') THEN
SHOW SPECIFICATIONS;
SELECT PARSE_JSON("definition"):SERVER_APPLICATION::STRING
INTO existing_target
FROM TABLE(RESULT_SCAN(LAST_QUERY_ID()));
IF(existing_target IS NOT NULL AND UPPER(existing_target) != UPPER(config_value)) THEN
EXECUTE IMMEDIATE 'ALTER APPLICATION DROP SPECIFICATION CONNECTION_' || UPPER(existing_target);
END IF;
spec_name := 'CONNECTION_' || UPPER(config_value);
EXECUTE IMMEDIATE
'ALTER APPLICATION SET SPECIFICATION ' || spec_name || '
TYPE = CONNECTION
LABEL = ''Server App''
DESCRIPTION = ''Request for an app that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2.''
SERVER_APPLICATION = ' || config_value || '
SERVER_APPLICATION_ROLES = (my_server_app_role)';
END IF;
RETURN 'success';
END;
$$;
CREATE APPLICATION ROLE IF NOT EXISTS client_app_user;
GRANT USAGE ON SCHEMA app_schema TO APPLICATION ROLE client_app_user;
ALTER APPLICATION SET CONFIGURATION DEFINITION my_server_app_name_configuration
TYPE = APPLICATION_NAME
LABEL = 'Server App'
DESCRIPTION = 'Request for an application that will provide access to server procedures and functions. The server app version must be greater than or equal to 3.2'
APPLICATION_ROLES = (client_app_user);
以下示例显示了客户端应用程序的清单文件 (manifest.yml):
manifest_version: 2
artifacts:
setup_script: setup.sql
lifecycle_callbacks:
before_configuration_change: app_schema.before_config_change_callback
请注意上述代码示例的以下几点:
在 before_configuration_change 回调中,应用程序会检查是否存在与配置的先前值匹配的现有连接规范,如果存在,则将其删除。然后,回调会为新提供的服务器应用程序名称创建新的连接规范。设置服务器名称后创建新连接可防止创建重复的连接规范。
示例:应用程序之间的异步通信¶
以下示例演示如何在服务器应用程序的安装脚本 (setup.sql) 中创建过程用于异步通信。服务器应用程序创建处理队列表,并通过应用程序角色向客户端应用程序提供两个过程:submit_request,将请求添加到队列中;fetch_response,检索已完成请求的结果。服务器应用程序定期使用 process_requests 过程来处理所有待处理请求。
CREATE TABLE IF NOT EXISTS app_schema.processing_queue (
request_id NUMBER AUTOINCREMENT,
operation STRING,
input STRING,
status STRING DEFAULT 'PENDING',
response STRING DEFAULT ''
);
CREATE OR REPLACE PROCEDURE app_schema.submit_request(operation STRING, input STRING)
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
BEGIN
INSERT INTO app_schema.processing_queue (operation, input) VALUES (:operation, :input);
RETURN 'Request submitted successfully';
END;
$$;
CREATE OR REPLACE PROCEDURE app_schema.process_requests()
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
DECLARE
-- Cursor to find all PENDING requests
c1 CURSOR FOR SELECT * FROM app_schema.processing_queue WHERE status = 'PENDING';
result STRING;
BEGIN
FOR request IN c1 DO
IF (request.operation = 'OPERATION_X') THEN
-- assuming there is a UDF func_x(input) to perform operation_x
result := (SELECT func_x(:request.input));
END IF;
-- update the processing queue with the result
LET stmt STRING :=
'UPDATE app_schema.processing_queue SET status = 'DONE', response = ' ||
result ||
' WHERE request_id = ' ||
request.request_id;
EXECUTE IMMEDIATE (:stmt);
END FOR;
RETURN 'Processed pending requests.';
END;
$$;
CREATE OR REPLACE PROCEDURE app_schema.fetch_response(operation STRING, input STRING)
RETURNS STRING
LANGUAGE SQL
EXECUTE AS OWNER
AS
$$
BEGIN
LET res STRING := (SELECT response FROM app_schema.processing_queue WHERE operation = :operation AND input = :input);
RETURN res;
END;
$$;
CREATE APPLICATION ROLE IF NOT EXISTS my_server_app_role;
GRANT USAGE ON SCHEMA app_schema TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.submit_request(string, string) TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.process_requests() TO APPLICATION ROLE my_server_app_role;
GRANT USAGE ON PROCEDURE app_schema.fetch_response(string, string) TO APPLICATION ROLE my_server_app_role;