蛙蛙推荐:蛙蛙牌云存储服务 摘要:最近云计算,云存储炒的是热火朝天,本蛙也来凑个热闹,和大家一起来DIY一个云存储服务。像live mesh目前就是个网络的OS,能把本机的东西存上去,也不是结构化的,我觉得云存储最好能够存储结构化的数据,而且管理起来要像数据库一样灵活。这样人人都可以把自己的备忘录,联系人信息放在自己的云存储服务里,并且方便的访问。
项目网址:http://www.codeplex.com/wawcloudstoreservice/
思路: 1、对已通过身份验证的用户每人分配一个目录,在这个目录里动态创建sqliet数据库 2、提供一套webservice接口来让用户创建数据结构,添加、获取及更新数据。 当然有人说了,人家google,亚马逊,ms的云存储多NB呀,自动负载均衡,高可靠性,速度又快,你这算啥呀,的确,我没有经过压力测试,不过据说sqlite的性能还不错,当然没有bigtable和hoodlop那些玩意牛了,本文主要是提供一种思路,接口有了,以后的实现可以慢慢来,对吧,以后慢慢来提高性能和稳定性,如果你做一个云存储服务一天就几百个人用,我觉得用sqlite都有点浪费,一切从需求出发。
困了,直接上代码算了,关于一些问题,咱们评论里再讨论
接口如下

namespace
?WasaSoft.StoreService



{
 ????public?enum?DataStoreType

 ???? {
 ????????Null,
 ????????Integer,
 ????????Real,
 ????????Text,
 ????????Blob,
 ????????IdentityInteger,
 ????}

 ????public?class?DictionayItem<T,V>

 ???? {
 ????????public?T?Key;
 ????????public?V?Value;
 ????}
 ????[WebServiceBinding(ConformsTo?=?WsiProfiles.BasicProfile1_1,?Name?=?"IDataStoreService",?Namespace?=?"http://pim.fetionmm.com/IDataStoreService/")]
 ????public?interface?IDataStoreService

 ???? {
 ????????[WebMethod(Description?=?"创建库")]
 ????????string?CreateDataBase();
 ????????[WebMethod(Description?=?"创建表")]
 ????????string?CreateTable(string?tableName,?List<DictionayItem<string,?DataStoreType>>?cols);
 ????????[WebMethod(Description?=?"增加数据")]
 ????????string?Add(string?tableName,string>>?data);
 ????????[WebMethod(Description?=?"获取所有数据")]
 ????????string?GetAll(string?tableName,List<string>?cols,?string?orderCol,?bool?isDesc);
 ????????[WebMethod(Description?=?"获取详细信息")]
 ????????string?GetDetail(string?tableName,?string?identityCol,?string?colValue);
 ????????[WebMethod(Description?=?"删除一条数据")]
 ????????string?DeleteOne(string?tableName,?string?colValue);
 ????????[WebMethod(Description?=?"批量删除数据")]
 ????????string?DeleteSome(string?tableName,?List<string>?identityCols);
 ????????[WebMethod(Description?=?"清空表")]
 ????????string?Clear(string?tableName);
 ????????[WebMethod(Description?=?"更新数据")]
 ????????string?Update(string?tableName,string?identityCol,?string?colValue,?string>>?data);
 ????}
 }


实现如下
 [WebService(Namespace?=?"http://tempuri.org/")]
 [WebServiceBinding(ConformsTo?=?WsiProfiles.BasicProfile1_1)]
 [ToolboxItem(false)]
 public?class?StoreService?:?WebService,?IDataStoreService


 {
 ????private?const?string?DbName?=?@"E:/huhao/project/WawaCloudStoreService/StoreService/bin/test.db3";


 ????IDataStoreService?成员#region?IDataStoreService?成员

 ????public?string?CreateDataBase()

 ???? {
 ????????if?(!File.Exists(DbName))?return?"出错";
 ????????File.Delete(DbName);
 ????????SQLiteConnection.CreateFile(DbName);
 ????????return?"ok";
 ????}

 ????public?string?CreateTable(string?tableName,?List<DictionayItem<string,?DataStoreType>>?cols)

 ???? {
 ????????DbProviderFactory?factory?=?SQLiteFactory.Instance;
 ????????using?(DbConnection?conn?=?factory.CreateConnection())

 ???????? {
 ????????????conn.ConnectionString?=?string.Format("Data?Source={0}",?DbName);
 ????????????conn.Open();

 ????????????StringBuilder?builder?=?new?StringBuilder();
 ????????????int?i?=?1;
 ????????????foreach?(DictionayItem<string,?DataStoreType>?col?in?cols)

 ???????????? {
 ????????????????string?colType?=?col.Value?==?DataStoreType.IdentityInteger
 ???????????????????????????????????????"INTEGER?PRIMARY?KEY"
 ?????????????????????????????????????:?col.Value.ToString();
 ????????????????builder.AppendFormat("{0}?{1}{2}",?col.Key,?colType,?i++?==?cols.Count???""?:?",");
 ????????????}

 ????????????string?sql?=?string.Format("create?table?[{0}]?({1})",?tableName,?builder);
 ????????????DbCommand?cmd?=?conn.CreateCommand();
 ????????????cmd.Connection?=?conn;
 ????????????cmd.CommandText?=?sql;
 ????????????cmd.ExecuteNonQuery();

 ????????????return?sql;
 ????????}
 ????}

 ????public?string?Add(string?tableName,?string>>?data)

 ???? {
 ????????DbProviderFactory?factory?=?SQLiteFactory.Instance;
 ????????using?(DbConnection?conn?=?factory.CreateConnection())

 ???????? {
 ????????????conn.ConnectionString?=?string.Format("Data?Source={0}",?DbName);
 ????????????conn.Open();
 ????????????DbCommand?cmd?=?conn.CreateCommand();

 ????????????StringBuilder?builder?=?new?StringBuilder();
 ????????????StringBuilder?builder2?=?new?StringBuilder();
 ????????????for?(int?i?=?0;?i?<?data.Count;?i++)

 ???????????? {
 ????????????????builder.AppendFormat("{0}?{1}",?data[i].Key,?(i?+?1)?==?data.Count???""?:?",");
 ????????????????builder2.AppendFormat("{0}?{1}",?"?",");
 ????????????????cmd.Parameters.Add(cmd.CreateParameter());
 ????????????}

 ????????????string?sql?=?string.Format("insert?into?{0}?({1})values({2})",?builder,?builder2);


 ????????????for?(int?i?=?0;?i?<?data.Count;?i++)

 ???????????? {
 ????????????????cmd.Parameters[i].Value?=?data[i].Value;
 ????????????}
 ????????????cmd.Connection?=?conn;
 ????????????cmd.CommandText?=?sql;
 ????????????cmd.ExecuteNonQuery();

 ????????????return?sql;
 ????????}
 ????}

 ????public?string?GetAll(string?tableName,?List<string>?cols,?string?orderCol,?bool?isDesc)

 ???? {
 ????????DbProviderFactory?factory?=?SQLiteFactory.Instance;
 ????????using?(DbConnection?conn?=?factory.CreateConnection())

 ???????? {
 ????????????StringBuilder?builder?=?new?StringBuilder();
 ????????????for?(int?i?=?0;?i?<?cols.Count;?i++)

 ???????????? {
 ????????????????builder.AppendFormat("{0}?{1}",?cols[i],?(i?+?1)?==?cols.Count???""?:?",");
 ????????????}
 ????????????string?sql?=?string.Format("select?{0}?from?{1}?ORDER?BY?{2}?{3}",?orderCol,
 ???????????????????????????????????????isDesc???"desc"?:?"asc");

 ????????????SQLiteDataAdapter?dataAdapter?=?new?SQLiteDataAdapter(sql,?string.Format("Data?Source={0}",?DbName));
 ????????????DataSet?ds?=?new?DataSet();
 ????????????dataAdapter.Fill(ds);

 ????????????StringWriter?sw?=?new?StringWriter();
 ????????????ds.WriteXml(sw);
 ????????????return?sw.ToString();
 ????????}
 ????}

 ????public?string?GetDetail(string?tableName,?string?identityCol,?string?colValue)

 ???? {
 ????????DbProviderFactory?factory?=?SQLiteFactory.Instance;
 ????????using?(DbConnection?conn?=?factory.CreateConnection())

 ???????? {
 ????????????conn.ConnectionString?=?string.Format("Data?Source={0}",?DbName);
 ????????????conn.Open();
 ????????????DbCommand?cmd?=?conn.CreateCommand();
 ????????????string?sql?=?string.Format("select?*?from?{0}?where?{1}=??limit?0,1",?identityCol);
 ????????????cmd.Connection?=?conn;
 ????????????cmd.CommandText?=?sql;
 ????????????cmd.Parameters.Add(cmd.CreateParameter());
 ????????????cmd.Parameters[0].Value?=?colValue;
 ????????????SQLiteDataAdapter?dataAdapter?=?new?SQLiteDataAdapter((SQLiteCommand)?cmd);
 ????????????DataSet?ds?=?new?DataSet();
 ????????????dataAdapter.Fill(ds);

 ????????????StringWriter?sw?=?new?StringWriter();
 ????????????ds.WriteXml(sw);
 ????????????return?sw.ToString();
 ????????}
 ????}

 ????public?string?Update(string?tableName,?string?colValue,
 ?????????????????List<DictionayItem<string,?string>>?data)

 ???? {
 ????????DbProviderFactory?factory?=?SQLiteFactory.Instance;
 ????????using?(DbConnection?conn?=?factory.CreateConnection())

 ???????? {
 ????????????conn.ConnectionString?=?string.Format("Data?Source={0}",?DbName);
 ????????????conn.Open();
 ????????????DbCommand?cmd?=?conn.CreateCommand();

 ????????????StringBuilder?builder?=?new?StringBuilder();
 ????????????for?(int?i?=?0;?i?<?data.Count;?i++)

 ???????????? {
 ????????????????builder.AppendFormat("{0}=??{1}",");
 ????????????????cmd.Parameters.Add(cmd.CreateParameter());
 ????????????}

 ????????????string?sql?=?string.Format("update?{0}?set?{1}?where?{2}=?",?identityCol);

 ????????????for?(int?i?=?0;?i?<?data.Count;?i++)

 ???????????? {
 ????????????????cmd.Parameters[i].Value?=?data[i].Value;
 ????????????}

 ????????????cmd.Parameters.Add(cmd.CreateParameter());
 ????????????cmd.Parameters[data.Count].Value?=?colValue;

 ????????????cmd.Connection?=?conn;
 ????????????cmd.CommandText?=?sql;
 ????????????cmd.ExecuteNonQuery();

 ????????????return?sql;
 ????????}
 ????}

 ????public?string?DeleteOne(string?tableName,?string?colValue)

 ???? {
 ????????DbProviderFactory?factory?=?SQLiteFactory.Instance;
 ????????using?(DbConnection?conn?=?factory.CreateConnection())

 ???????? {
 ????????????conn.ConnectionString?=?string.Format("Data?Source={0}",?DbName);
 ????????????conn.Open();
 ????????????DbCommand?cmd?=?conn.CreateCommand();
 ????????????string?sql?=?string.Format("delete?from?{0}?where?{1}=?",?identityCol);
 ????????????cmd.Connection?=?conn;
 ????????????cmd.CommandText?=?sql;
 ????????????cmd.Parameters.Add(cmd.CreateParameter());
 ????????????cmd.Parameters[0].Value?=?colValue;
 ????????????cmd.ExecuteNonQuery();
 ????????????return?sql;
 ????????}
 ????}

 ????public?string?DeleteSome(string?tableName,?List<string>?identityCols)

 ???? {
 ????????foreach?(string?s?in?identityCols)

 ???????? {
 ????????????DeleteOne(tableName,?identityCol,?s);
 ????????}
 ????????return?"ok";
 ????}

 ????public?string?Clear(string?tableName)

 ???? {
 ????????DbProviderFactory?factory?=?SQLiteFactory.Instance;
 ????????using?(DbConnection?conn?=?factory.CreateConnection())

 ???????? {
 ????????????conn.ConnectionString?=?string.Format("Data?Source={0}",?DbName);
 ????????????conn.Open();
 ????????????DbCommand?cmd?=?conn.CreateCommand();
 ????????????string?sql?=?string.Format("delete?from?{0}",?tableName);
 ????????????cmd.Connection?=?conn;
 ????????????cmd.CommandText?=?sql;
 ????????????cmd.ExecuteNonQuery();
 ????????????return?sql;
 ????????}
 ????}

 ?

 ????#endregion
 }


单元测试如下,其中StoreService.StoreService是web服务的代理类 ?
 class
?Program



{
 ????static?void?Main(string[]?args)

 ???? {
 ????????try

 ???????? {

 ????????????CreateDatabase#region?CreateDatabase
 ????????????StoreService.StoreService?service?=?new?StoreService.StoreService();
 ????????????Console.WriteLine(service.CreateDataBase());
 ????????????Console.WriteLine("创建数据库成功");?
 ????????????#endregion


 ????????????CreateTable#region?CreateTable
 ????????????List<DictionayItemOfStringDataStoreType>?cols?=?new?List<DictionayItemOfStringDataStoreType>();
 ????????????DictionayItemOfStringDataStoreType?item?=?new?DictionayItemOfStringDataStoreType();
 ????????????item.Key?=?"id";
 ????????????item.Value?=?DataStoreType.IdentityInteger;
 ????????????cols.Add(item);

 ????????????item?=?new?DictionayItemOfStringDataStoreType();
 ????????????item.Key?=?"name";
 ????????????item.Value?=?DataStoreType.Text;
 ????????????cols.Add(item);

 ????????????item?=?new?DictionayItemOfStringDataStoreType();
 ????????????item.Key?=?"password";
 ????????????item.Value?=?DataStoreType.Text;
 ????????????cols.Add(item);

 ????????????Console.WriteLine(service.CreateTable("mytable",?cols.ToArray()));
 ????????????Console.WriteLine("创建表成功");?
 ????????????#endregion


 ????????????AddData#region?AddData
 ????????????List<DictionayItemOfStringString>?toAddData?=?new?List<DictionayItemOfStringString>();
 ????????????
 ????????????DictionayItemOfStringString?dataItem?=?new?DictionayItemOfStringString();
 ????????????dataItem.Key?=?"name";
 ????????????dataItem.Value?=?"蛙蛙王子";
 ????????????toAddData.Add(dataItem);

 ????????????dataItem?=?new?DictionayItemOfStringString();
 ????????????dataItem.Key?=?"password";
 ????????????dataItem.Value?=?"www.cnblogs.com";
 ????????????toAddData.Add(dataItem);

 ????????????Console.WriteLine(service.Add("mytable",?toAddData.ToArray()));

 ????????????toAddData[0].Value?=?"谁染枫林醉";
 ????????????toAddData[1].Value?=?"www.fetionmm.com";
 ????????????Console.WriteLine(service.Add("mytable",?toAddData.ToArray()));

 ????????????toAddData[0].Value?=?"onlytiancai";
 ????????????toAddData[1].Value?=?"www.fetionmm.com";
 ????????????Console.WriteLine(service.Add("mytable",?toAddData.ToArray()));

 ????????????Console.WriteLine("添加数据成功");
 ????????????#endregion


 ????????????GetAll#region?GetAll

 ????????????Console.WriteLine(service.GetAll("mytable",new?string[] {"name"},??"id",?false));?
 ????????????Console.WriteLine("获取所有数据成功");
 ????????????#endregion


 ????????????GetDetails#region?GetDetails
 ????????????Console.WriteLine(service.GetDetail("mytable",?"id",?"1"));
 ????????????Console.WriteLine("获取详细数据成功");?
 ????????????#endregion


 ????????????Update#region?Update
 ????????????List<DictionayItemOfStringString>?toUpdateData?=?new?List<DictionayItemOfStringString>();
 ????????????dataItem?=?new?DictionayItemOfStringString();
 ????????????dataItem.Key?=?"password";
 ????????????dataItem.Value?=?"mm.fetionmm.com";
 ????????????toUpdateData.Add(dataItem);
 ????????????Console.WriteLine(service.Update("mytable",?"1",?toUpdateData.ToArray()));

 ????????????Console.WriteLine(service.GetAll("mytable",?new?string[]? {?"id","password"?},?false));
 ????????????Console.WriteLine("更新数据成功");
 ????????????#endregion


 ????????????DeleteOne#region?DeleteOne
 ????????????Console.WriteLine(service.DeleteOne("mytable",?"1"));

 ????????????Console.WriteLine(service.GetAll("mytable",?new?string[]? {?"id",?"password"?},?false));
 ????????????Console.WriteLine("删除一条数据成功");
 ????????????#endregion


 ????????????DeleteSome#region?DeleteSome

 ????????????Console.WriteLine(service.DeleteSome("mytable",?new?string[]? {?"2"?}));

 ????????????Console.WriteLine(service.GetAll("mytable",?new?string[]? {?"id",?false));
 ????????????Console.WriteLine("删除多条数据成功");
 ????????????#endregion


 ????????????Clear#region?Clear
 ????????????Console.WriteLine(service.Clear("mytable"));

 ????????????Console.WriteLine(service.GetAll("mytable",?new?string[]? {?"id",?false));
 ????????????Console.WriteLine("清空数据成功");
 ????????????#endregion


 ????????}
 ????????catch?(Exception?ex)

 ???????? {
 ????????????Console.Write(ex);
 ????????}
 ????????Console.ReadKey();
 ????}
 }
? 相关链接(依旧不是自动链接,要想打开链接,自己复制到地址栏吧,谁让博客园不支持自动链接呢) Setting a breakpoint in managed code using Windbg http://blogs.msdn.com/kristoffer/archive/2007/01/02/setting-a-breakpoint-in-managed-code-using-windbg.aspx [转]如何高效使用SQLite .net (C#) http://www.cnblogs.com/yelsea/archive/2007/06/21/792314.html Sqlite.net 2.0使用笔记 http://www.sqlitechina.org/html/1/20071221/70.html http://extrafliu.blogspot.com/search/label/Sqlite.net%202.0?????¨???è?° SQLite 第三版中的数据类型 http://www.sqlite.com.cn/MySqlite/5/127.Html sqlite3数据类型的请教?? http://topic.csdn.net/u/20080825/23/e364b41f-2c56-499f-a7a2-7bc629b67c36.html http://sourceforge.net/project/showfiles.php?group_id=132486 SQLite不支持的SQL语法总结 http://www.sqlite.com.cn/MySqlite/3/250.Html 101个Google技巧 - Google技巧的终极收集 http://www.cnbeta.com/articles/64073.htm 云计算 http://www.hudong.com/wiki/%E4%BA%91%E8%AE%A1%E7%AE%97 云中漫步——迎接云计算时代的到来 http://www.googlechinablog.com/2008/05/blog-post_09.html 《互联网周刊》:“云计算”的容量 http://www.cnbeta.com/articles/64169.htm Google App Engine 初体验 http://www.javaeye.com/news/2066 Google App Engine入门 http://www.webfuny.cn/2008/08/09/app-engine-g.html 补充 这个服务写的很简单,要想真的投入使用,还要考虑很多东西 1、身份验证:web服务的身份验证一般用单独的soap header来做,可以把从单点登录获取的凭证放在soap header里,服务端取出凭证,验证凭证,获取用户信息,并找到用户的profile,比如用户的数据库路径在哪里,是否是VIP用户,数据库配额是多少等等。关于基于令牌的web服务身份验证,可以看以下链接,http://www.cnblogs.com/onlytiancai/archive/2006/08/16/478095.html,当然这个方案很简单,没有使用对称加密等技术,关于SSO大家可以搜索一下相关帖子。 2、安全限制:安全在这里包括多方面,比如一个用户频繁的调用一个耗费资源很大的服务,或者传入一个超级大的参数,或者从数据库里select了10M的数据,或者由于杀毒软件查杀数据库是否有病毒,访问数据库的众多线程被hang住,造成IIS线程池耗尽等,因为这些,所以要在web服务外层加一个安全控制服务,控制用户的流量,以及细化代码,找出可能引擎服务器长时间执行的请求,把它拒绝掉。其它的sql语句等用户爱怎么写怎么写,反正数据库是它自己的,弄坏了也怪他自己。然后还可以考虑给用户增加一些磁盘配额等措施。 3、异常处理:本文例子没有进行任何异常处理,web service用soap exception来处理错误,所以在服务端出现异常后要包装成soap exception返回给用户,关于这种操作,博客园有多人说过。 4、可靠性:用无数的sqliet数据库来保存用户信息,当然不是最可靠的方式,以后再考虑一些容错的方案,比如用开源的hadoop等。但是用户多了,可以用多台机器来存储用户信息,前段收到用户请求后根据用户名的哈希值去寻找他的数据应该从哪台存储服务器上去读取,或者直接302重定向到另一台前端服务器上,这也算是负载均衡了。 5、性能:考虑在前端做一些缓存服务,尤其是对读操作,设计良好的读缓存能很有效的提高服务器性能,因为大多数请求时读操作,写缓存也可以考虑,看写请求的量来评估了,网上也有不少开源的缓存服务组件,Memcache,java的oscache,微软的企业库里的缓存块等,大家可以研究下用起来。
6、前端展现:光有了服务不行,要想让用户使,还得有个界面,web服务自身的特性让它可以和多种平台交互,所以我们可以为这个服务做多界面的应用,用delphi,c#,python甚至yui+google gear,只要能访问web服务,都可以做一个界面来使用我的云存储服务。当然app engine最大的特点就是有调用web服务的API,大家做app engine应用的时候可以考虑用下俺的云存储服务。
我知道live mesh要把live id,live contacts,live mail,live desktop,live office都要集成到一起,微软内部还有reddog,BitVault等项目来对抗开源和google的map/reduce,hadoop,bigtable,gfs等东西的。我发此帖的意思是不是只有大 公司才能推出云这个云那个,自己有好的想法也能去实现去,现在云计算,云存储等概念都不成熟,甚至salesforce等托管CRM厂商也说自己是云计算 服务,还有adobe的Adobe Share和ms的windows live skydrive就是一个网络硬盘,也成为云存储,那其它的AllMyData、Box.net、eSnips、 Freepository、GoDaddy、iStorage、Mofile、 Mozy、Omnidrive、Openomy、Streamload、 Strongspace以及Xdrive等更是云存储了,我觉得这些东西本质上和FTP有啥区别呀,就是弄了一套rest api或者一个ajax ui,用户也就是在上面存储一些文档文件啥的,存结构化数据不方便(当然上面列举的一些产品和服务我没有一一进行详细的了解,是看资料了解的,有些可能说 的不对。)。其它还有sun的Hydrazine计划及Insight计划,亚马逊的EC2云计算服务,EBS云存储服务,IBM的蓝云计划等,当然大公 司争的是企业市场,我们自己做云服务就针对个人来展开了,或者是把某一点做精。
参考: 云计算井喷
http://server.zdnet.com.cn/server/2008/0422/825478.shtml
云计算——IBM的未来策略 http://laiba.tianya.cn/laiba/CommMsgs?cmm=14452&tid=2592400139121650923 IBM云计算数据中心 http://www.freerainbow.cn/2008/08/03/ibm-yunjisuan.html 亚马逊发力企业云计算市场
http://www.builder.com.cn/2008/0415/815771.shtml
Sun实施云计算Insight 计划挑战微软Live Mesh
http://www.cnzz.cn/NewsInfo/6180.aspx
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|