PowerBuilder应用开发系列讲座(35)


分布式应用开发

   在 第8 期 中, 我 们 曾 经 介 绍 了 开 发 一 个 简 单 分 布 式 应 用 的 步 骤, 这 里 我 们 不 再 赘 述 开 发 的 全 过 程, 只 是 就 其 中 的 主 要 内 容 再 重 点 说 明 一 下。

不 可 视 对 象(NVO) 及 其 代 理 对 象(proxy)

   不 可 视 对 象: 不 可 视 对 象 最 早 在3.0 中 引 入, 功 能 在 以 后 的 每 一 个 版 本 中 都 得 到 一 定 的 加 强。 简 单 的 说, 不 可 视 对 象 是 一 个 进 程 对 象。 在 这 个 对 象 中, 没 有 任 何 可 视 的 成 份, 因 此 而 得 名。 不 可 视 对 象 可 以 是 一 个 事 务 处 理 的 对 象。 由 一 些 事 务 处 理 函 数 组 成, 并 有 一 个 方 法 集 作 为 外 界 访 问 接 口。 用 户 通 过 这 个 由 函 数 和 事 件 组 成 的 方 法 集 调 用 事 务 处 理 函 数。 在 分 布 式PowerBuilder 中, 我 们 将 这 样 的 不 可 视 对 象 放 在 了 远 端。 使 事 务 处 理 的 函 数 在 应 用 服 务 器 中 或 者 说 在 另 外 的 一 台 计 算 机 中 运 行。

   代 理 对 象: 我 们 在 不 可 视 对 象 的 外 部 增 加 了 一 层 包 装, 把 这 一 层 作 为 编 程 的 接 口 层(API)。 这 就 是 该 不 可 视 对 象 的 代 理 对 象(proxy), 代 理 对 象 作 为 不 可 视 对 象 的 最 外 层 包 装, 有 与 该 对 象 相 同 的public 访 问 特 性 的 方 法 和 属 性。 将 实 际 的 对 象 与 代 理 对 象 分 离 开, 这 就 形 成 了 分 布 式 的 结 构。 不 可 视 对 象 所 进 行 的 事 务 处 理 放 在 了 应 用 服 务 器 上, 而 它 的 代 理 对 象 放 在 了 客 户 端。

   在 客 户 端, 用 户 对 代 理 对 象 进 行 操 作, 但 这 只 是 不 可 视 对 象 的 一 个API 接 口, 它 并 不 包 含 真 正 的 方 法。 代 理 在 内 部 重 新 调 用 运 行 在 远 端 的 对 象 的 方 法。 在 服 务 器 一 端, 运 行 着 的 是 一 个 真 正 的 不 可 视 对 象, 它 同 普 通 的 不 可 视 对 象 没 有 任 何 不 同 之 处, 只 是 对 这 个 不 可 视 对 象 的 调 用 是 在 客 户 端 通 过 它 的 代 理 进 行 的。 每 一 个 运 行 在 服 务 器 端 的 对 象 在 客 户 端 都 必 须 有 它 的 代 理, 这 个 对 象 才 能 够 被 该 客 户 端 的 应 用 程 序 所 调 用。 一 个 应 用 服 务 器 可 能 会 有 多 个 客 户 机, 这 样 在 一 个 服 务 器 上 的 不 可 视 对 象 就 可 能 在 客 户 机 上 有 多 个 不 同 的 代 理。

连 接 对 象(connection) 及 传 输 对 象(transport)

   介 绍 了 服 务 器 端 的 不 可 视 对 象 和 客 户 端 的 代 理 对 象 这 两 个 在 分 布 式 应 用 中 的 对 等 部 分, 接 下 来 我 们 要 考 虑 的 是 如 何 将 这 两 个 部 分 建 立 连 接。 在 连 接 的 过 程 中, 我 们 就 要 涉 及 另 两 个 对 等 的 对 象, 这 就 是 在PowerBuilder5.0 中 新 增 加 的 两 个 对 象 类 型: 连 接(connection) 及 传 输(transport) 对 象。connection 对 象 是 在 客 户 端 用 以 同 服 务 器 进 行 通 讯 的 对 象, 反 过 来,transport 对 象 是 驻 留 在 服 务 器 端 用 以 同 客 户 端 应 用 进 行 通 讯 的 对 象。

   connection 对 象: 我 们 可 以 将 这 一 对 象 同 用 在 数 据 库 事 务 的transaction 对 象 进 行 类 比。 我 们 通 过 定 义transaction 对 象 的 属 性 连 接 某 个 数 据 库 服 务 器。 在 客 户 端 的 应 用 中, 用 数 据 窗 口 或 直 接 使 用SQL 访 问 数 据 库 服 务 器 时, 我 们 须 使 用SetTransObject() 函 数 或USING 关 键 词 来 指 定 这 个 数 据 窗 口 所 使 用 的transaction 对 象。 同 理, 分 布 式 事 务 中, 客 户 端 的 代 理 对 象 就 如 同 一 个 数 据 窗 口, 我 们 也 应 当 指 定 代 理 对 象 同 哪 个 服 务 器 进 行 通 讯。 因 为 正 如 一 个 数 据 窗 口 可 以 访 问 不 同 的 数 据 库 服 务 器 一 样, 一 个 代 理 对 象 也 可 以 代 理 不 同 应 用 服 务 器 上 的 不 可 视 对 象, 而 其 中 的connection 对 象 就 象transaction 对 象 一 样, 它 的 属 性 就 是 用 以 区 别 不 同 的 服 务 器。 在connection 对 象 中 最 重 要 的 三 个 属 性 是application、 driver、 location。driver 属 性 是 用 以 指 定 我 们 所 使 用 的 通 讯 协 议, 目 前 支 持 的 是TCP/IP 和Named Pipes;location 属 性 是 应 用 服 务 器 的 名 称。

   象 事 务 对 象 中 使 用CONNECT USING SQLCA 一 样, 接 下 来 我 们 调 用 一 个connection 的 对 象 函 数ConnectToServer(), 建 立 客 户 和 应 用 服 务 器 的 连 接。 也 正 如 事 务 对 象 一 样, 在 调 用 这 个 函 数 后, 我 们 应 检 验connection 的 返 回 值, 以 确 认 连 接 是 否 成 功。connection 对 象 同 服 务 器 建 立 连 接 后, 客 户 端 即 可 同 服 务 器 进 行 通 话。 下 一 步 我 们 指 定 代 理 对 象 使 用 哪 一 个 连 接 对 象。 这 就 好 比 是 在 数 据 窗 口 中 使 用SetTransObject 函 数 将 数 据 窗 口 和 事 务 对 象 建 立 联 系, 代 理 对 象 使 用 的 的 是SetConnect() 函 数。 一 个PowerBuilder 的 应 用 可 以 同 时 连 接 多 个 数 据 库 服 务 器, 同 样 在 分 布 式PowerBuilder 中, 您 也 可 以 同 时 建 立 多 个 连 接 对 象, 每 个 连 接 对 象 同 不 同 的 应 用 服 务 器 相 连, 使 一 个 客 户 端 应 用 可 以 同 时 访 问 多 个 应 用 服 务 器。

   传 输 对 象: 在 客 户 端 我 们 使 用 的 是connection 对 象 同 服 务 器 进 行 联 系, 而 在 服 务 器 端 我 们 使 用 的 是transport 对 象 同 客 户 端 进 行 连 接。transport 对 象 用 以 指 示 本 应 用 服 务 器 的 一 些 属 性 值, 并 且 将 这 个 应 用 服 务 器 启 动 起 来。transport 也 有 着 两 个 重 要 的 属 性application 和driver。 同 样driver 是 指TCP/IP 或Named Pipe 协 议, 而application 是 指 正 在 监 听 的 应 用 名 称。 启 动 服 务 器 的 函 数 是listen(), 执 行 了 这 个 函 数 后, 在 服 务 器 端 就 增 加 了 一 个 进 程 用 于 监 听 任 何 客 户 端 的 请 求。

分 布 式PowerBuilder 的 工 作 原 理

   当 一 个connection 对 象 调 用 了ConnectToServer 函 数 成 功 后, 服 务 器 端 将 在 内 存 中 开 辟 一 个 用 于 该 客 户 端 应 用 的 工 作 区, 而 在proxy 对 象 调 用 了SetConnect 函 数 后, 系 统 将 在 服 务 器 端 初 始 化 一 个 不 可 视 对 象 的 实 例, 注 意 系 统 并 不 是 在 用 户 初 始 化 代 理 对 象 时 初 始 化 不 可 视 用 户 对 象 的, 而 是 在 调 用SetConnect 函 数 后, 在 服 务 器 端 对NVO 进 行 初 始 化 的。

   分 布 式PowerBuilder 在 服 务 器 一 端 实 现 的 是 一 个 虚 拟 机 模 型。 每 当 一 个 客 户 请 求 连 接 时, 服 务 器 就 会 在 内 存 中 建 立 一 个 新 的 区 域 用 于 该 客 户 的 请 求, 每 一 个 内 存 空 间 都 是 相 互 独 立。 在PowerBuilder 5.0 中 分 布 式 应 用 只 支 持 同 步 方 式, 也 就 是 说, 当 您 调 用 代 理 对 象 的 一 个 函 数 时, 系 统 实 际 将 调 用 服 务 器 端 的 不 可 视 对 象 的 函 数。 这 时 客 户 端 应 用 将 被 挂 起, 直 至 服 务 器 函 数 运 行 完 毕, 客 户 端 才 能 继 续 工 作。 而 在 即 将 发 布 的6.0 中 将 支 持 异 步 运 算。

   当 您 调 用 一 个 客 户 端 函 数 时, 您 一 定 需 要 传 递 参 数 给 这 个 函 数。 目 前 的 分 布 式PowerBuilder 版 本 可 以 支 持 多 种 数 据 类 型 的 传 递: 所 有 简 单 的 数 据 类 型, 结 构 和 数 组, 使 用 传 值 法 和 传 参 法。 还 支 持 传 递 不 可 视 对 象。 不 过 不 能 以 引 用 方 式 传 递 对 象, 例 如 您 不 能 在 分 布 式 中 传 递 一 个 窗 口 或 一 个 数 据 窗 口 的 句 柄。

   当 我 们 在 使 用 完 一 个 代 理 对 象 后 应 注 意 在 程 序 的 结 束 前 用destroy 语 句 析 构 这 个 对 象 实 例, 否 则 将 出 现 我 们 在 第13 期 曾 经 讨 论 过 的 内 存 漏 洞(memory leak) 的 问 题。 而 这 一 点 在 分 布 式 中 尤 为 重 要。 因 为 对 代 理 的 析 构 将 使 远 端 的 不 可 视 对 象 同 时 析 构。 如 果 您 忘 记 了 对 代 理 对 象 的 析 构, 不 可 视 对 象 将 不 会 在 服 务 器 端 自 动 清 除, 这 样 您 将 在 客 户 和 服 务 器 两 端 都 造 成 了 内 存 漏 洞。 此 外connection 对 象 还 有 一 个DisconnectServer 函 数, 这 个 函 数 用 以 取 消 客 户 与 服 务 器 的 连 接。 服 务 器 端 将 回 收 分 配 给 该 用 户 的 内 存, 在 程 序 结 束 时 不 使 用 这 个 函 数 也 将 造 成 服 务 器 器 端 的 内 存 漏 洞。 在 客 户 端 产 生 了 内 存 漏 洞 也 许 并 不 会 造 成 多 么 恶 劣 的 影 响, 在 服 务 器 端 有 一 个10K 左 右 的 漏 洞 可 能 也 算 不 得 什 么, 但 是 如 果 每 一 次 的 客 户 调 用NVO 函 数 都 造 成10K 的 漏 洞, 一 个 客 户 机 每 天 有100 次 的 调 用, 这 个 服 务 器 如 连 接 了100 个 客 户 机, 那 么 一 天 之 内 就 会 造 成102.4M 的 内 存 漏 洞, 这 足 以 使 任 何 强 壮 的 服 务 器 崩 溃。

   开 发 分 布 式 应 注 意 的 问 题

上 期 错 误 更 正

   在8 月25 日 所 刊 出 的 第32 期 中, 我 们 介 绍 了 为 下 拉 式 数 据 窗 口 建 立 数 据 缓 冲 服 务 器, 我 们 也 可 以 使 用 分 布 式PowerBuilder 将 这 个 小 应 用 分 成 两 部 分, 把 缓 冲 区 建 在 应 用 服 务 器 上。 只 要 对 原 文 中 的 部 分 代 码 稍 加 修 改 就 可 以 完 成 这 个 分 布 式 应 用。 不 过 在 该 文 中 的wf_find_dataobject 函 数 却 有 一 个 严 重 的 错 误, 笔 者 误 将 应 当 用 在datawindow 中 的 代 码 用 在 了 这 里。 准 确 的 代 码 应 当 是 将 原 程 序 中 第14 行 至 第16 行 该 为:


        lds_new_entry = create u_dsa

   IF IsNull(lds_new_entry) THEN 

      RETURN 0

   END IF

   衷 心 地 感 谢 向 我 指 出 这 一 错 误 深 圳 现 代 计 算 机 公 司 的 刘 伟 青 先 生, 同 时, 对 该 文 的 读 者 表 示 深 深 的 歉 意。