简体   繁体   English

如何在客户端仍然连接时更新DataSnap服务器?

[英]How can I update a DataSnap server while clients are still connected?

We use stateful DataSnap servers for some business logic tasks and also to provide clientdataset data. 我们将有状态DataSnap服务器用于某些业务逻辑任务,并提供clientdataset数据。

If we have to update the server to modify a business rule, we copy the new version into a new empty folder and register it (depending on the Delphi version, just by launching or by running the TRegSvr utility). 如果我们必须更新服务器以修改业务规则,我们将新版本复制到一个新的空文件夹并注册它(取决于Delphi版本,只需启动或运行TRegSvr实用程序)。

We can do this even while the old server instance is running. 即使旧的服务器实例正在运行,我们也可以这样做。 However, after registering the new version, all new client connections will still use the currently running (old) server instance . 但是, 在注册新版本后,所有新客户端连接仍将使用当前运行的(旧)服务器实例 All clients have to disconnect first, then the new server will be used for the next clients. 所有客户端必须先断开连接,然后新服务器将用于下一个客户端。

Is there a way to direct all new client connections to the new server , immediately after registering? 有没有办法在注册后立即将所有新客户端连接定向到新服务器

(I know that new or changed method signatures will also require a change and restart of the clients but this question is about internal modifications which do not affect the interface) (我知道新的或更改的方法签名也需要更改并重新启动客户端,但这个问题是关于不影响接口的内部修改)

We are using Socket connections, and all clients share the same server application (only one application window is open). 我们正在使用Socket连接,并且所有客户端共享相同的服务器应用程序(只打开一个应用程序窗口)。 In the early days we have used a different configuration of the remote datamodule which resulted in one app window per client. 在早期,我们使用了远程数据模块的不同配置,这导致每个客户端有一个应用程序窗口。 Maybe this could be a solution? 也许这可能是一个解决方案? (because every new client will launch the currently registered executable) (因为每个新客户端都会启动当前注册的可执行文件)

Update: does Delphi XE offer some support for 'hot deployment' (of updated servers)? 更新:Delphi XE是否为“热部署”(更新服务器)提供了一些支持? We use Delphi 2009 at the moment but would upgrade to XE if it offers easier implementation of 'hot deployment'. 我们目前使用Delphi 2009,但如果能够更轻松地实现“热部署”,则会升级到XE。

you could separate your appserver into 2 new servers, one being a simple proxy object redirecting all methods (and optionally containing state info if any) to the second one actually implementing your business logic. 您可以将appserver分成2个新服务器,一个是简单的代理对象,将所有方法(以及可选的包含状态信息)重定向到实际实现业务逻辑的第二个。 you also need to implement "silent reconnect" feature within your proxy server in order not to disturb connected clients if you decide to replace business appserver any time you want. 您还需要在代理服务器中实现“静默重新连接”功能,以便在您决定随时更换业务应用服务器时不会干扰已连接的客户端。 never did such design myself before but hope the idea is clear 从来没有做过这样的设计,但希望这个想法很明确

Have you tried renaming the current server and placing the new in the same location with the correct name (versus changing the registry location). 您是否尝试重命名当前服务器并将新服务器放在具有正确名称的相同位置(而不是更改注册表位置)。 I have done this for COM libraries before with success. 在成功之前,我已经为COM库做了这个。 I am not sure if it would apply to remote launch rules through as it may look for an existing instance to attach to instead of a completely fresh server. 我不确定它是否适用于远程启动规则,因为它可能会寻找一个现有的实例来连接而不是一个完全新鲜的服务器。

It may be a bit hackish but you would have the client call a method on the server indicating that a newer version is available. 它可能有点hackish但您可以让客户端在服务器上调用一个方法,指示有更新的版本可用。 This would allow it to perform any necessary cleanup so it doesn't end up talking to both the existing server instance and new server instance at the same time. 这将允许它执行任何必要的清理,因此它不会同时与现有服务器实例和新服务器实例进行通信。

There is probably not a simple answer to this question, and I suspect that you will have to modify the client. 这个问题可能没有一个简单的答案,我怀疑你将不得不修改客户端。 The simplest solution I can think of is to have a flag (a property or an out parameter on some commonly called method) on the server that the client checks periodically that tells the client to disconnect and reconnect (called something like ImBeingRetired). 我能想到的最简单的解决方案是在服务器上有一个标志(一个通常称为方法的属性或out参数),客户端定期检查它,告诉客户端断开连接并重新连接(称为ImBeingRetired)。

It's also possible to write callbacks under certain circumstances for datasnap (although I've never done this). 在某些情况下也可以为datasnap编写回调(尽管我从未这样做过)。 This would allow the server to inform the client that it should restart or reconnect. 这将允许服务器通知客户端它应该重新启动或重新连接。

The last option I can think of (that hasn't already been mentioned) would be to make the client/server stateless, so that every time the client wants something it connects, gets what it wants then disconnects. 我能想到的最后一个选项(尚未提及)将使客户端/服务器无状态,以便每次客户端想要连接的东西时,获得它想要的东西然后断开连接。

Unfortunately none of these options are the answer you want to your question, but might give you some ideas. 不幸的是,这些选项都不是您想要的答案,但可能会给您一些想法。

For newer versions (Delphi 2010 and up), there is an interesting solution 对于较新的版本(Delphi 2010及更高版本),有一个有趣的解决方案

  • for systems using the HTTP transport: 对于使用HTTP传输的系统:

Implementing Failover and Load Balancing in DataSnap 2010 by Andreano Lanusse 在Andrean Lanusse的DataSnap 2010中实现故障转移和负载平衡

  • and a related question for the TCP/IP transport: 以及TCP / IP传输的相关问题:

How to direct DataSnap client connections to various DS Servers? 如何将DataSnap客户端连接到各种DS服务器?

I have done something similar by having a specific table which held my "data version". 通过拥有一个特定的表来保存我的“数据版本”,我做了类似的事情。 Each time I would update the server or change a system wide global setting, I would increment this field. 每次我更新服务器或更改系统范围的全局设置时,我都会增加此字段。 When a client starts it always checks this value, and will check again before any transactions/queries. 当客户端启动时,它始终检查此值,并在任何事务/查询之前再次检查。 If the value was ever different from when I first started, then I needed to go through my re-initialization logic, which could easily include a re-login to an updated server. 如果该值与我刚开始时的值不同,那么我需要通过我的重新初始化逻辑,这可以很容易地包括重新登录到更新的服务器。

I was using IIS to publish my app servers, so the data that would change would be the path to the app server. 我使用IIS发布我的应用服务器,因此更改的数据将是应用服务器的路径。 I kept the old ones available, to respond to any existing transactions that were in play. 我保留旧的,以回应任何现有的交易。 Eventually these would be removed once I knew there were no more client connections to that version. 一旦我知道没有更多的客户端连接到该版本,这些将被删除。

You could easily handle knowing what versions to keep around if you log what server the client last connected too (and therefore would know about). 如果您记录客户端上次连接的服务器(因此可以了解),您可以轻松地知道要保留哪些版本。

  1. (optional) set up vmware vSphere, ESX, or find a hosting service that already has one. (可选)设置vmware vSphere,ESX或查找已有的托管服务。
  2. Store the session variables in db. 将会话变量存储在db中。
  3. Prepare 2 web boxes with 2 distinct IP address and deploy your stuff. 准备2个具有2个不同IP地址的网箱并部署您的资料。
  4. Set up DNS, firewall, load balancer, or BSD vm so name "example.com" resolves to web box 1. 设置DNS,防火墙,负载均衡器或BSD虚拟机,因此名称“example.com”解析为Web框1。
  5. Deploy new version to web box 2. 将新版本部署到Web框2。
  6. Switch over to web box 2 using whatever routing method you chose. 使用您选择的任何路由方法切换到Web框2。
  7. Deploy new version to web box 1 if things look ok. 如果事情看起来不错,请将新版本部署到Web框1。

Using DNS is probably easiest, but it takes time for the mapping to propagate to the client (if the client is outside your LAN) and also two clients may see different results. 使用DNS可能是最简单的,但是映射传播到客户端需要时间(如果客户端在LAN之外),并且两个客户端可能会看到不同的结果。 Some firewalls have IP address mapping feature that you can map public IP address and internal IP address. 有些防火墙具有IP地址映射功能,可以映射公共IP地址和内部IP地址。 The ideal way is to use load balancer and configure it to 50:50 and change it to 100:0 when you want to do upgrade, but it costs money. 理想的方法是使用负载均衡器并将其配置为50:50并在需要升级时将其更改为100:0,但这需要花钱。 A cheaper alternative is to run software load balancer on BSD vm, but it probably requires some work. 更便宜的替代方案是在BSD vm上运行软件负载均衡器,但它可能需要一些工作。

Edit : What I meant to say is session variables, not session. 编辑 :我的意思是会话变量,而不是会话。 You said the server is stateful. 你说服务器是有状态的。 If it contains some business logic that uses session variable, it needs to get stored externally to be preserved across reconnection during switch over. 如果它包含一些使用会话变量的业务逻辑,则需要在外部存储以在切换期间通过重新连接保留。 Actual DataSnap session will be lost, so when you shutdown web box 1 during upgrade, the client will get "Session {some-uuid} is not found" error by web box 1, and it will reconnect to web box 2. Also you could use 3 IP addresses (1 public and 2 private) so the client always sees 1 address , which is better method. 实际的DataSnap会话将丢失,因此当您在升级期间关闭Web框1时,客户端将通过Web框1获取“找不到会话{some-uuid}”错误,并且它将重新连接到Web框2.此外,您可以使用3个IP地址(1个公共地址和2个私有地址),因此客户端总是看到1个地址,这是更好的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何“冻结” Datasnap服务器中的数据集? - How can I 'freeze' a dataset in a Datasnap server? 如何更新Delphi Datasnap服务器? - How to update Delphi Datasnap server? 连接到DataSnap Server的设备列表 - List of devices connected to DataSnap Server 如何在DCOMCNFG中找到DataSnap服务器? - How do I find the DataSnap server in DCOMCNFG? 我卡住了,如何在 datasnap rest Delphi 中实现 2 种不同的服务器方法 - I'm stuck, how can I implement 2 different server methods in datasnap rest Delphi 如何在本地网络上为独立的Datasnap Rest Server创建/安装SSL证书 - How can I create/install a SSL Cert for a standalone Datasnap Rest Server on local network 如何在Datasnap Server Methods单元中获取经过身份验证的用户名和密码? - How can I obtain the authenticated Username and Password in a Datasnap Server Methods unit? 如何在Delphi 2010 DataSnap Server中访问/修改请求/响应的标头 - How can I access/modify headers of request/reponses in a Delphi 2010 DataSnap Server 我可以声明带有数组参数的datasnap服务器方法吗? - Can I declare a datasnap server method with array parameters? 如何抑制Delphi DataSnap错误消息对话框? - How can I supress Delphi DataSnap error message dialogs?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM