主要内容

在已部署档案中管理应用程序状态

此示例展示如何管理部署到的应用程序存档中的持久数据MATLAB®生产服务器™.它使用MATLAB制作服务器MATLAB函数执行的RESTful API(MATLAB Production Server)和JSON来连接一个或多个MATLAB应用程序实例到部署在服务器上的存档。

MATLAB制作服务器工人没有国籍。持久化提供了一种机制,通过在对部署在服务器上的MATLAB代码的多个调用之间缓存数据来维护状态。多个工作人员可以访问缓存的数据。

该示例描述了两个工作流。

  1. 在将应用程序部署到服务器之前,用于在MATLAB桌面环境中测试应用程序功能的测试工作流。

  2. 使用活动对象的部署工作流MATLAB制作服务器实例来部署存档。

为了演示如何使用持久性,本示例使用了旅行推销员问题,该问题涉及寻找城市之间最短的可能路线。这个实现存储了一个持久的MATLAB对象在数据缓存中。城市构成了图的节点,城市之间的距离构成了与图边相关的权重。在这个例子中,图是一个完整的图。测试工作流使用本地版本的寻路功能。部署工作流使用打包到存档并部署到服务器的路由查找功能。MATLAB应用程序调用寻路函数。这些函数将图形数据读写到缓存中。

示例的代码位于,其中MPS_INSTALL美元是这个位置MATLAB制作服务器安装。

控件创建的可部署归档文件生产服务器编译器App,你一定要有版本的MATLAB运行时安装,它与您用于创建存档的MATLAB版本兼容。有关更多信息,请参见支持MATLAB运行时版本的MATLAB生产服务器(MATLAB Production Server)

第一步:写作MATLAB使用持久性函数的代码

  1. 编写一个函数来初始化持久数据

    编写一个函数来检查数据缓存中是否存在城市和距离图。如果图表不存在,请从Excel中创建它®包含距离数据的电子表格,并将其写入缓存。因为只有一个MATLAB制作服务器Worker每次都可以执行这个写操作,使用同步锁来确保数据初始化只发生一次。

    连接到存储距离数据的缓存,如果它不存在,则使用mps.cache.connect(MATLAB Production Server).在互斥锁上使用mps.sync.mutex(MATLAB Production Server)在写操作期间。一旦数据写入缓存,就释放锁。

    方法初始化距离数据loadDistanceData函数。

    函数tf = loadDistanceData(connectionName, cacheName) c = mps.cache.connect(cacheName,“连接”, connectionName);尝试次数= 0;isKey (c,“距离”) == false && tries < 6 lk = mps.sync.mutex(“DistanceData”“连接”, connectionName);如果获得(路、10)如果isKey (c,“距离”== false g = initDistanceData(“Distances.xlsx”);c.距离= g;结束释放(路);结束尝试=尝试+ 1;结束tf = isKey(c,“距离”);结束
  2. 编写函数来读取持久数据

    写一个函数从数据缓存中读取距离数据图。因为从缓存读取数据是一个幂等操作,所以不需要使用同步锁。使用连接到缓存mps.cache.connect然后检索图像。

    方法从缓存中读取图形并将其转换为单元格数组listDestinations函数。

    计算可能的最短路径findRoute函数。使用最近邻算法,从一个给定的城市开始,反复访问下一个最近的城市,直到访问所有的城市。

    函数c = mps.cache.connect(“TravelingSalesman”“连接”“剪贴板”);如果loadDistanceData (“剪贴板”“TravelingSalesman”) ==错误错误('加载距离数据失败。不能继续。);结束g = c.距离;目标= table2array(g.Nodes);结束
    函数[route,distance] = findRoute(start,destinations) c = mps.cache.connect(“TravelingSalesman”“连接”“剪贴板”);如果loadDistanceData (“剪贴板”“TravelingSalesman”) ==错误错误('加载距离数据失败。不能继续。);结束g = c.距离;路由= {start};距离= 0;当前=开始;~isempty(目的地)minDistance = Inf;nextSegment = {};N = 1: nummel (destinations) [p,d] = shortestpath(g,current,destinations{N});如果d < minDistance nextSegment = p(2:end);minDistance = d;结束结束current = nextSegment{end};距离=距离+ minDistance;目的地= setdiff(目的地,当前);route = [route nextSegment];结束结束
  3. 编写一个函数来修改持久数据

    写一个函数来添加一个新城市。添加城市将修改存储在数据缓存中的图形。因为此操作需要写入缓存,所以使用mps.sync.mutex函数(如步骤1所示)用于锁定。添加一个城市后,通过确认每对城市之间的距离是已知的,来检查图表是否仍然完整。

    属性添加一个城市addDestination函数。添加一个城市将添加一个新的图形节点的名字以及将该节点连接到图中所有现有节点的新边。新添加边的权值由向量给出距离目的地是字符向量的单元格数组,其中包含图中其他城市的名称。

    函数count = addDestination(名称,目的地,距离)count = 0;C = mps.cache.connect(“TravelingSalesman”“连接”“剪贴板”);如果loadDistanceData (“剪贴板”“TravelingSalesman”) ==错误错误('加载距离数据失败。不能继续。);结束Lk = mps.sync.mutex(“DistanceData”“连接”“剪贴板”);如果acquire(lk,10) g = c.距离;newDestinations = setdiff(g.Nodes. setdiff)名字,目的地);如果~ isempty (newDestinations)错误(“议员:例子:TSP: MissingDestinations”...为缺失的目的地添加距离:%s...strjoin (newDestinations”、“));结束SRC = repmat({name},1,numel(目的地));G = adddge (G, src,目的地,距离);c.距离= g;释放(路);Count = numnodes(g);结束结束

  4. 编写一个调用寻路函数的MATLAB应用程序

    编写一个MATLAB应用程序,将步骤2和步骤3中描述的函数封装在各自的代理函数中。该应用程序允许您指定主机和端口。为了进行测试,当主机为空且端口为0时,调用本地版本的寻路功能。对于部署工作流,在运行在指定主机和端口上的服务器上调用已部署的函数。使用webwrite函数发送HTTP POST请求到服务器。

    有关如何编写应用程序的更多信息,请参见使用应用程序设计器创建并运行一个简单的应用程序

    编写代理函数findRouteProxyaddDestinationProxy,listDestinationProxyfindRouteaddDestination,listDestination函数,分别。

    函数目的地= listDestinationsProxy(app)如果isempty (app.HostEditField.Value) & &...app.PortEditField.Value <= 0 destinations = listDestinations();返回结束listDestinations_OPTIONS = weboptions(“MediaType”“application / json”“超时”现年60岁的“ContentType”“生”);listDestinations_HOST = app.HostEditField.Value;listDestinations_PORT = app.PortEditField.Value;noInputJSON ='{"rhs": [], "nargout": 1}';destinations_JSON =...webwrite (sprintf (“http://%s: % d / TravelingSalesman / listDestinations”,listDestinations_HOST,listDestinations_PORT), noInputJSON, listDestinations_OPTIONS);如果iscolumn(destinations_JSON), destinations_JSON = destinations_JSON';结束destinations_RESPONSE = mps.json. decoderresponse (destinations_JSON);如果isstruct (destinations_RESPONSE)错误(destinations_RESPONSE.id destinations_RESPONSE.message);其他的如果nargout > 0,目的地= destinations_RESPONSE{1};结束结束结束
    函数[route,distance] = findRouteProxy(app,start,destinations)如果isempty (app.HostEditField.Value) & &...app.PortEditField.Value <= 0 [route,distance] = findRoute(start,destinations);返回结束findRoute_OPTIONS = weboptions(“MediaType”“application / json”“超时”现年60岁的“ContentType”“生”);findRoute_HOST = app.HostEditField.Value;findRoute_PORT = app.PortEditField.Value;start_destinations_DATA = {};如果nargin > 0, start_destinations_DATA = [start_destinations_DATA {start}];结束如果nargin > 1, start_destinations_DATA = [start_destinations_DATA {destinations}];结束route_distance_JSON =...webwrite (sprintf (“http://%s: % d / TravelingSalesman / findRoute”、findRoute_HOST findRoute_PORT), mps.json.encoderequest (start_destinations_DATA“nargout”nargout) findRoute_OPTIONS);如果iscolumn(route_distance_JSON), route_distance_JSON = route_distance_JSON';结束route_distance_RESPONSE = mps.json. decoderresponse (route_distance_JSON);如果isstruct (route_distance_RESPONSE)错误(route_distance_RESPONSE.id route_distance_RESPONSE.message);其他的如果nargout > 0, route = route_distance_RESPONSE{1};结束如果nargout > 1,距离= route_distance_RESPONSE{2};结束结束结束
    函数count = addDestinationProxy(应用程序,名称,目的地,距离)如果isempty (app.HostEditField.Value) & &...app.PortEditField.Value <= 0 count = addDestination(名称,目的地,距离);返回结束addDestination_OPTIONS = weboptions(“MediaType”“application / json”“超时”现年60岁的“ContentType”“生”);addDestination_HOST = app.HostEditField.Value;addDestination_PORT = app.PortEditField.Value;name_destinations_distances_DATA = {};如果nargin > 0, name_destinations_distances_DATA = [name_destinations_distances_DATA {name}];结束如果nargin > 1, name_destinations_distances_DATA = [name_destinations_distances_DATA {destinations}];结束如果nargin > 2, name_destinations_distances_DATA = [name_destinations_distances_DATA{距离}];结束count_JSON =...webwrite (sprintf (“http://%s: % d / TravelingSalesman / addDestination”、addDestination_HOST addDestination_PORT), mps.json.encoderequest (name_destinations_distances_DATA“nargout”nargout) addDestination_OPTIONS);如果iscolumn(count_JSON), count_JSON = count_JSON';结束count_RESPONSE = mps.json. decoderresponse (count_JSON);如果isstruct (count_RESPONSE)错误(count_RESPONSE.id count_RESPONSE.message);其他的如果nargout > 0, count = count_RESPONSE{1};结束结束结束

步骤2:在测试工作流中运行示例

在MATLAB桌面环境中测试示例代码。要做到这一点,将位于的所有文件复制到系统上的可写文件夹,例如,/ tmp / persistence_example.启动MATLAB桌面,设置当前工作目录为/ tmp / persistence_example使用cd命令。

控件从MATLAB桌面控制持久性服务,用于测试目的mps.cache.control(MATLAB Production Server)函数。此函数返回一个mps.cache.Controller(MATLAB Production Server)对象,该对象管理本地持久性服务的生命周期。

  1. 创建一个mps.cache.Controller对象用于使用Redis™持久性提供程序的本地持久性服务。

    >> CTRL = mps.cache.control(“剪贴板”“复述”“端口”, 8675);

    激活时,该控制器启用名为便条簿.连接名称将缓存链接到持久性服务中的存储位置。的mps.cache.connect函数需要连接名来创建数据缓存。的MATLAB制作服务器管理员在缓存配置文件中设置连接名称mps_cache_config.详细信息请参见配置服务器使用Redis(MATLAB Production Server).通过在MATLAB桌面会话中使用相同的连接名称,您可以使代码从开发到测试再到生产而无需更改。

  2. 使用启动持久性服务开始(MATLAB Production Server)

    > >开始(ctrl);
  3. 启动TravelingSalesman使用持久化服务的寻路应用。

    > > TravelingSalesman

    应用程序以默认值启动宿主而且港口

    点击负载的城市加载城市列表。使用开始菜单来设置起始位置和>>而且<<用于选择和取消要访问的城市的按钮。点击计算路径显示访问所有城市的路线。

  4. 关闭应用程序时,停止使用的持久性服务停止(MATLAB Production Server).停止持久性服务将删除该服务存储的数据。

    > >停止(ctrl);

步骤3:在部署工作流中运行示例

要在部署工作流中运行示例,请将位于的所有文件复制到系统上的可写文件夹,例如,/ tmp / persistence_example.启动MATLAB桌面,设置当前工作目录为/ tmp / persistence_example使用MATLABcd命令。

部署工作流在MATLAB桌面环境之外管理持久性服务的生命周期,并调用部署到服务器的归档文件中打包的路由查找函数。

  1. 创建一个MATLAB制作服务器实例

    从系统命令行创建服务器mps-new(MATLAB Production Server).有关更多信息,请参见使用命令行创建服务器实例(MATLAB Production Server).如果尚未设置服务器环境,请参见mps-setup(MATLAB Production Server)获取更多信息。

    创建一个新服务器server_1位于文件夹中tmp

    mps-new / tmp / server_1

    或者,使用MATLAB制作服务器仪表板来创建服务器。有关更多信息,请参见设置和登录到MATLAB生产服务器仪表板(MATLAB Production Server)

  2. 创建持久性服务连接

    可部署归档需要名为便条簿.控件使用仪表板创建便条簿连接或复制文件mps_cache_config从示例目录转移到服务器实例的配置目录。如果你已经有了mps_cache_config文件,编辑它以添加便条簿连接,在示例中指定mps_cache_config

  3. 使用Production Server Compiler App创建一个可部署的存档,并将其部署到服务器

    1. 开放生产服务器编译器应用程序

      • MATLAB工具条:在应用程序选项卡,在应用程序部署,点击生产服务器编译器

      • MATLAB命令提示符:输入productionServerCompiler

    2. 应用程序类型菜单中,选择可部署的存档

    3. 导出功能字段,添加findRoute.mlistDestinations.m而且addDestination.m

    4. 档案信息,将存档重命名为TravelingSalesman

    5. 运行存档所需的其他文件,添加Distances.xlsx

    6. 点击

    7. 生成的可部署存档TravelingSalesman.ctf位于for_redistribution项目文件夹。复制TravelingSalesman.ctf文件到auto_deploy服务器文件夹,/ tmp / server_1 / auto_deploy在本例中,用于托管。

  4. 启动服务器实例

    从系统命令行启动服务器mps-start(MATLAB Production Server)

    mps-start -C /tmp/server_1 . txt
    或者,使用仪表板启动服务器。

  5. 启动持久性服务

    从系统命令行启动持久性服务mps-cache(MATLAB Production Server)

    mps-cache开始- c/ tmp / server_1——连接便条簿
    或者,使用仪表板启动和附加持久性服务。

  6. 测试应用程序

    启动TravelingSalesman使用持久化服务的寻路应用。

    > > TravelingSalesman

    应用程序以空值开始宿主而且港口.请参考服务器配置文件main_config位于server_name/配置获取的主机和端口值MATLAB制作服务器实例。对于本例,在/ tmp / server_1 /配置.在应用程序中输入主机和端口值。

    点击负载的城市加载城市列表。使用开始菜单来设置起始位置和>>而且<<用于选择和取消要访问的城市的按钮。点击计算路径显示访问所有城市的路线。

测试环境工作流和部署环境工作流的结果是相同的。

另请参阅

||||||

相关的话题

Baidu
map