代码改变世界

Effective C# 学习笔记(二十八)创建基于网络分布式部署的APIs

2011-07-16 22:45  小郝(Kaibo Hao)  阅读(359)  评论(0编辑  收藏  举报

现在越来越多应用采用分布式部署,这种部署方式受限于带宽和并发事务。对于此类应用你应该提供低频率的事务操作和尽量少数据量交互,也就是尽量少的运用有限的带宽来传输数据。下面举例说明该如何设计你的APIs

 

假设有一个订单交易系统,通过Call Center来完成客户的订单交易。这时你会涉及到一个客户对象。代码如下所示:

public class Customer

{

public Customer()

{

}

// Properties to access and modify customer fields:

public string Name { get; set; }

public Address ShippingAddr { get; set; }

public Account CreditCardInfo { get; set; }

}

//若你每次操作该对象都通过远程访问其会很消耗资源的,代码如下:

// create customer on the server.

Customer c = Server.NewCustomer();

// round trip to set the name.

c.Name = dlg.Name;

// round trip to set the addr.

c.ShippingAddr = dlg.ShippingAddr;

// round trip to set the cc card.

c.CreditCardInfo = dlg.CreditCardInfo;

 

不如在客户端先创建好对象,再传输到后台服务器,代码如下:

// create customer on the client.

Customer c2 = new Customer();

// Set local copy

c2.Name = dlg.Name;

// set the local addr.

c2.ShippingAddr = dlg.ShippingAddr;

// set the local cc card.

c2.CreditCardInfo = dlg.CreditCardInfo;

// send the finished object to the server. (one trip)

Server.AddCustomer(c2);

 

想像一下这个系统有100万的用户,每个用户平均15个订单/年,那么个这应用该如何设计才能保证效率呢?

首先,你会想到一次返回所有用户的订单不现实,100*15/=1500+万个/次。由于Call Center 的接线员一次只处理一个用户的订单,所以你会想到要根据用户名来过滤某个用户的订单。所以查询订单的方法你会定义如下:

public OrderDataCollection FindOrders(string customerName)

{

// Search for the customer by name.

// Find all orders by that customer.

}

而这时你进一步回想用户一般只会查询正在进行中的订单,所以你会写下如下方法(又减少的数据量):

public OrderData FindOpenOrders(string customerName)

{

// Search for the customer by name.

// Find all orders by that customer.

// Filter out those that have already

// been received.

}

 

假设用户是来自全国各地的,那么你的查询又可以根据省份地区过滤了,对于某一地区的接线员其查询某一地区的客户信息及客户相关订单的查询方法优化如下(这样减少了多次查询数据库的操作):

public CustomerSet RetrieveCustomerData(

AreaCode theAreaCode)

{

// Find all customers for a given area code.

// Foreach customer in that area code:

// Find all orders by that customer.

// Filter out those that have already

// been received.

// Return the result.

}

//这个方法只返回自上一次被更改时间后被更改的订单信息的记录集合

public CustomerSet UpdateCustomer(CustomerData

updates, DateTime lastUpdate, AreaCode theAreaCode)

{

// First, save any updates.

// Next, get the updates:

// Find all customers for a given area code.

// Foreach customer in that area code:

// Find all orders by that customer that have been

// updated since the last time. Add those to the result

// Return the result.

}

 

此外,考虑到客户并不是每日都会更新订单信息。所以,根据客户订单频率的统计,你可能会得出6个月内没有新订单的用户不会再近期有新订单,所以这样的数据可以被过滤掉。还有,那些刚刚进行订单操作的用户,可能只关心他最后一个订单,所以对于此类查询,你可只用返回该用户的最后一个订单即可。

 

最后总结下:你可能需要在降低事务操作数据大小和执行频率间进行权衡,根据实际的业务需求,尽量少执行更大的事务操作。