之前因为某些特定岗位的人不知道是不方便还是什么的原因,所以随便做了个独立于所有系统之外的邮件审批服务,功能是那些人在邮件里给待审批单据发个“同意”就自动审批通过,大致分为3部分:第一部分每隔固定时间去邮件服务器抓一批邮件下来;第二部分分析邮件格式,如果符合就提取必须的邮件内容;第三部分提交审批流驱动进行审批。
我一直想做个移动端APP然后废掉它算了,不过似乎领导觉得这个东西还能撑下去,总之就一时半会是不可能干掉了。
所以,游戏之做还是得优化一下,这里就说说第一部分:
每隔固定时间抓取然后执行存在的问题,比如说现在是每隔十分钟抓一次,处理不怎么及时,而且即使没有新邮件也会去抓一次,另外还有一个隐藏的问题,就是为什么设置10分钟,主要是邮件服务器那边还有其他的处理,需要一个回执,但是这是个单线程的服务(因为用的人很少)所以担心设置的时间短了这一批抓取的还没处理完,这里有一些无关的事都耦合上了。
解决办法:不再去抓邮件,而是如果邮件审批服务空闲了,就去邮件服务器上注册一下,如果有了新邮件,就由邮件服务器发布任务,这样以后用的人多了还可以做分布式处理(当然,我还是倾向于不用这种方式了,因为各种客户端发出来的邮件千奇百怪,解析难保正确)。
本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/net/
这里就使用WCF的订阅发布来做了,其实我觉得在没什么压力的情况下,有些消息队列也可以用这种方法简化
下面是测试代码:
首先是配置文件
<service name="HotelService.PublishService"> <endpoint address="" binding="wsDualHttpBinding" contract="HotelService.IPublishService" /> <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service>
服务和回调契约:
[ServiceContract(CallbackContract = typeof(ISubscribeCallback), Namespace = "http://www.justonlyatest.com")] public interface IPublishService { [OperationContract(IsOneWay = true)] void DoWork(); [OperationContract(IsOneWay = true)] void Subscribe(string id); [OperationContract(IsOneWay = true)] void UnSubscribe(string id); } public interface ISubscribeCallback { [OperationContract]//(IsOneWay = true) void CallbackWork(string workState); }
服务实现,注释里简单交代了下实例模型下的效果
// InstanceContextMode.Single 同步通知所有订阅的客户端,可将服务作为版本服务器的客户端,同步分布式服务的版本信息 // InstanceContextMode.PerSession 同步同一Session下的所有订阅,本例中单个客户端实例的所有订阅 // InstanceContextMode.PerCall 由于所有请求都是独立服务实例,所以无法实现订阅 // ConcurrencyMode.Single 回调必须是IsOneWay // 回调是IsOneWay时可同步通知所有订阅方,否则只能顺序通知 [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)] public class PublishService : IPublishService { Subscribers subscribers = new Subscribers(); public void DoWork() { string workState = "完成"; //ISubscribeCallback callback = OperationContext.Current.GetCallbackChannel<ISubscribeCallback>(); //callback.CallbackWork(workState); Dictionary<string, ISubscribeCallback> subscribes = subscribers.Subscribes; foreach (var key in subscribes.Keys) { subscribes[key].CallbackWork(key + ":" + workState); } } public void Subscribe(string id) { ISubscribeCallback callback = OperationContext.Current.GetCallbackChannel<ISubscribeCallback>(); subscribers.AddSubscriber(id, callback); } public void UnSubscribe(string id) { ISubscribeCallback callback = OperationContext.Current.GetCallbackChannel<ISubscribeCallback>(); subscribers.RemoveSubscriber(id, callback); } }
public class Subscribers { public Dictionary<string, ISubscribeCallback> Subscribes { get; set; } public Subscribers() { Subscribes = new Dictionary<string, ISubscribeCallback>(); } public void AddSubscriber(string id,ISubscribeCallback callback) { if (!Subscribes.Keys.Contains(id)) { Subscribes.Add(id, callback); } } public void RemoveSubscriber(string id, ISubscribeCallback callback) { if (Subscribes.Keys.Contains(id)) { Subscribes.Remove(id); } } }
客户端测试
PublishService.PublishServiceClient client; string clientID; public TestSubscribe() { InstanceContext context = new InstanceContext(new CallbackSubscribe()); client = new PublishService.PublishServiceClient(context); clientID = Guid.NewGuid().ToString(); } private void btnTest_Click(object sender, EventArgs e) { client.DoWork(); } private void btnRegist_Click(object sender, EventArgs e) { client.Subscribe(clientID); } private void btnCancellation_Click(object sender, EventArgs e) { client.UnSubscribe(clientID); }
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索string
, 邮件
, callback
, 邮件服务器
, public
, IsOneWay
, subscribe
void
wcf 订阅发布、使用wcf的三级联动、wcf使用、wcf nettcp 无法使用、wcf使用tcp传输文件,以便于您获取更多的相关知识。