如果我的服务器上有数百/数千台客户端计算机WCP,我是否应该回复“200 OK”类型的消息,说明我已收到数据并将其成功存储在数据库中?
这已经内置到WCF中了吗?
答案 0 :(得分:18)
这里提到了三种消息模式:
所有三个都显示不同的消息传递行为,应根据您的需要选择要使用的模式。
对于在数据持久保存到数据库时向客户端返回成功的要求,选项1或3是合适的。
这是默认配置。
一旦服务完成其所有任务,这将在同一http连接上返回200响应。这意味着在等待响应时对服务的调用将会阻塞 - 您的客户端将挂起,直到服务已写入数据库并完成所需的任何其他操作。
只要传输层和消息传递基础结构层成功,就会返回202响应。返回的202表示该消息已被接受。来自http rfc:
请求已被接受处理,但处理尚未完成。 (......)202回复是故意不承诺的。
这意味着只要服务基础结构成功启动了服务,您的客户端就会继续执行,并且您将不会收到有关数据库调用是否成功的信息。
与选项2类似,响应是http 202,而不是200,但现在当您从客户端调用服务时,您提供了一个InstanceContext
对象,该对象指定了一个处理回调的对象。客户端重新获得控制权,并且新线程异步等待服务响应,通知您成功或失败。
以下是有关在WCF中实现这些模式的更多信息。写完之后,它很长,但有一些有用的注释和代码。
正如Whisk所提到的,Juval Lowy有一篇文章涵盖了很多细节(以及更多!)here
这是WCF中的默认行为,因此您不需要执行任何操作 - 它适用于许多不同的绑定,包括wsHttpBinding和basicHttpBinding。
有一点需要注意的是,即使你有一个无效的操作,你的客户端等待200响应所描述的行为也会发生:
[ServiceContract]
interface IMyServiceContract
{
[OperationContract]
void DoSomeThing(InputMessage Message);
}
要将操作设置为单向操作,只需将其装饰为:
[ServiceContract]
interface IMyServiceContract
{
[OperationContract(IsOneWay = true)]
void DoSomeThing(InputMessage Message);
}
以这种方式装饰的方法必须只有返回类型的void。一个问题是该服务将很乐意构建,并且您不会得到一个例外,说服务配置在连接之前是无效的。
用于创建双工回叫服务的接口代码为:
[ServiceContract(CallbackContract = typeof(IMyContractCallback))]
interface IMyContract
{
[OperationContract(IsOneWay=true)]
void DoSomeThing(InputMessage Message);
}
public interface IMyContractCallback
{
[OperationContract(IsOneWay = true)]
void ServiceResponse(string result);
}
在客户端,您需要这样的设置回调:
public class CallbackHandler : IMyContractCallback
{
#region IEchoContractCallback Members
public void ServiceResponse(string result)
{
//Do something with the response
}
#endregion
}
// And in the client when you set up the service call:
InstanceContext instanceContext = new InstanceContext(new CallbackHandler());
MyContractClient client = new MyContractClient(instanceContext);
InputMessage msg = new InputMessage();
client.DoSomething(msg);
在服务中你可能会有一些代码:
class MyContractImplementation : IMyContract
{
public void DoSomeThing(MyMessage Message)
{
string responseMessage;
try
{
//Write to the database
responseMessage = "The database call was good!";
}
catch (Exception ex)
{
responseMessage = ex.Message;
}
Callback.ServiceResponse(responseMessage);
}
}
需要注意的一件重要事情是,一开始就把我弄出来,就是要注意例外情况。如果你:
消耗异常,您将不会收到错误警告(但会发生回调)
抛出未处理的异常,服务将终止,客户端甚至不会收到回调。
与选项1相比,这是此方法的一大缺点,选项1将在抛出未处理的异常时返回异常。
答案 1 :(得分:2)
默认情况下,除非抛出异常,否则您的服务将向客户端返回“OK”消息(即使您的服务方法指定了void返回类型)。客户端将等到收到此消息后再继续使用它。
因此,根据您的问题,您将获得默认情况下所需的行为。
如果您不想这样,我会同意Whisk并将您的操作标记为One Way(操作合同中的设置)。
祝你好运!答案 2 :(得分:1)
有两种方法可以做到这一点 - 从wcf调用中返回一个表示成功或失败的值,或者假设成功并使用回调告诉客户端是否存在问题。
我的偏好是使用one-way的duplex service服务调用,并使用该服务的回调合同来通知客户端失败。对回调合约here和here有很好的描述。
如果您遵循第二条路径,我认为您会获得更好,更异步的架构,但对于简单的应用程序而言,只需返回成功或失败就可能更容易。
答案 3 :(得分:0)
我认为这个问题可以使用更多细节来正确回答。主要的,您目前使用哪种类型的绑定?
如果您正在使用支持可靠性的绑定,并且您只是想确保从客户端那个服务器确实收到了消息,那么只需打开可靠性就可以了。有了这个,WCF会自动地在会话的每一边说: “你说对了?” “我明白了。你明白了吗?” “我明白了。”