.NET应用架构设计—面向查询服务的参数化查询设计(分解业务点,单独配置各自的数据查询契约)
阅读目录:
- 1.背景介绍
- 2.对业务功能点进行逻辑划分(如:A、B、C分别三个业务点)
- 2.1.配置映射关系,对业务点配置查询契约(构造VS插件方便生成查询契约)
- 2.2.将配置好的映射策略文件放在调用端,与服务不耦合
- 3.Dynamic、Dom动态构造服务端对象(Dynamic、DOM实现动态DOM)
1.背景介绍
现在越来越多的公司都在尝试SOA架构的实践,本人最近也在尝试学习这方面的技术,但是在实践过程中遇到一个问题,我想这个问题也是我们普遍实践者都应该会遇到的问题,问题描述如下:
我们有一个SOA商品(Item)查询接口,这个接口很通用,主要用来支撑日常很多其他系统的大量关于Item的查询,尤其是在高峰期间该服务的压力是很大的;我们站在SOA的角度看这个接口,这个通用的接口解决了众多的查询业务,确实不错,但是我们切换一下角度,站在每一个调用接口的访问端看似乎并不是很满意或者说牺牲了部分性能上的代价,因为我们无法干净利落的只获取当前这个业务点需要的数据项;这个Item服务接口所返回的数据项必须同时满足所有调用它的业务点,哪怕这次调用我只需要用到Item的三分之一的数据字段都不行,每次都会把不需要的字段都查询出来,不管是返回的性能、查询的性能,其实都是可以通过调整设计来避免的;
以往我们的思路都是集中在服务端,常规做法都是提供了一个能够容纳所有查询客户端需求的数据实体,客户端可选择的余地很有限,无法只获取自己所需要的几个数据项,甚至各个业务点在不同的情况下都有可能需要两到三个数据返回实体;总而言之,面向数据查询的服务接口如果要向着SOA方向发展那就必须包含SOA设计上的相关原则,如这里的面向查询为主的服务设计其实就是缺少SOA原则中的”服务应具有策略性“一原则;
为什么以往一直没有暴露出这个问题呢,是因为以往都是在本地直接调用“查询引擎”,如:SQLSERVER,在“查询引擎”的最后一层就是应用程序,而应用程序中可以编写很多彼此类似的查询方法,每个方法可能只有一两个字段的差异性,或者通过“企业应用架构模式—查询对象模式”来将不同的方法合在一起通过一个可以调整查询字段的对象来配置本次需要的查询字段;由于现在我们已将查询服务化,就不太可能再去为了所有客户端在去适应性的去扩充类似没有太大价值的接口,但是客户端又需要将自己所需要的查询字段让服务知道,所以这里的解决方案可以称为面向SOA的”企业应用架构模式—查询对象模式“;
本文将通过运用”关注点分离“通用设计思想来对查询服务在服务端的强耦合进行分解,将强耦合从服务端迁移出来通过策略性的配置将关注点放入各自的客户端,从而有效的解决服务不再臃肿的问题,如果理解上有困难可以尝试使用面向SOA的”企业应用架构模式—查询对象模式“概念来理解;
2.对业务功能点进行逻辑划分(如:A、B、C分别三个业务点)
首先我们需要将相对于服务来说的客户端中所有业务点进行逻辑划分,将原本一个高耦合的庞大数据实体分解成各自所需要的一个精简的数据实体;业务点的划分目地在于可以将数据实体能与之对应起来,这个数据实体是针对于查询服务而言的,对于客户端来说没有任何的依赖和约束,也就是说本次业务点发起的查询将把这个数据实体转化成一组查询策略中的设置带到服务端中,然后服务端在根据这组策略信息进行组合最终的查询语句;
注:这里的数据实体并不是服务端定义的DTO,也不是客户端定义的DTO,而是一个只跟本次业务查询相关的数据查询实体,该实体不是一个定义的类,而是一个策略,类似:
A.Business{Query field{ItemNumber、Description、PromationPrice}}
这样一组配置信息;客户端用来反序列化的DTO可以是一个庞大的共用的数据实体,也可以是跟业务点绑定的精简实体,对于查询没有任何影响,我们要解决的是“只查询我所需要的数据项,只返回我所需要的数据项”,而跟你在服务端、客户端定义的用来辅助序列化的实体没有任何关系;
将查询的字段、返回的字段通过查询策略带入到服务端,我们就能够知道本次业务点查询的是需要什么样的字段,然后就可以在构造查询引擎参数时将返回的字段直接加上或者过滤不需要的;
2.1.配置映射关系,对业务点配置查询契约(构造VS插件方便生成查询契约)
将系统中需要调用服务接口的所有功能点进行业务点逻辑划分设计后,每个业务点都需要在自己发起调用服务的时候能够带上在之前某个时间点设计好的查询契约,这个用来生成查询契约的工具最好是集成在VisualStudio中的自定义插件,在设计时用来动态构造一个对应的契约配置文件,如果可以的话可以采用动态代码方案,将配置文件的静态文件通过动态生成代码的方式嵌入到生成的代码中去,减少不需要的配置文件,也减少查询框架的性能开销,一次生成后就可以直接使用;
2.2.将配置好的映射策略文件放在调用端,与服务不耦合
本篇文章的解决方案最大的突破点就是将关注点从服务端转移到所有客户端上,将原本都集中在服务上的所有客户端的需求分离出去,每个需要调用服务的客户端维护好自己的一份查询契约,在每次调用服务的时候带上那份契约;如果处于性能考虑每次带上契约会增加开销,那么可以在第一次身份验证的时候在服务上确认,以后调用都忽略;
这样一来服务将精简很多,通过同样的设计方法可以用来设计很多类似的服务接口,将关注点从服务上转移到客户端上,会是一个很好的设计思路;
3.Dynamic、Dom动态构造服务端对象(Dynamic、DOM实现动态DOM)
借助C#新特性Dynamic,我们可以在.NET平台上进行动态编程,这里可以解决我们预先定义服务端实体的好处;以往我们需要在服务上定义一个至少能容纳所有客户端查询契约中的所有数据项的实体,但是当我们运用动态编程时,我们无需事先定义一个类,而可以在运行时动态获取对象属性,当然这得益于.NETDLR的实现;再适当的结合DOM思想,我们就可以实现一个动态DOM效果,对于DOM的某个Element的访问也无需定义映射实体然后在通过属性获取,中间既增加了序列化的开销还增加了开发工作量;
using System;
using System.Collections.Generic; namespace ConsoleApplication1.DynamicDom
{
public class ItemEntity : System.Dynamic.DynamicObject
{
/// <summary>
/// 可以使用LINQ TO XML或者将XML数据构造在一个指定的容器中,用来判断是否存在
/// </summary>
private static Dictionary<string, object> itemPropery = new Dictionary<string, object>();
static ItemEntity()
{
itemPropery.Add("ItemNumber", );
itemPropery.Add("PromationPrice", );
}
public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result)
{
if (itemPropery.ContainsKey(binder.Name))
{
result = itemPropery[binder.Name];
return true;
}
result = null;
return false;
}
}
}
dynamic itemEntity = new DynamicDom.ItemEntity();
Console.WriteLine("ItemNumber:" + itemEntity.ItemNumber);
Console.WriteLine("PromationPrice:" + itemEntity.PromationPrice);
Console.ReadLine();
这里只是一个简单的示例,目的是想让并不太了解Dynamic的朋友有了直观上的认识;通过使用Dynamic、Dom可以在服务端上无需定义任何的实体,根据各个客户端传过来的配置直接进行动态访问,可以借助LIQN TO XML;
全文仅仅是一个设计上的介绍,要想完全实现上面这些效果需要还是需要开发些东西的,这里只是抛砖引玉,希望对正在设计相关内容的朋友提供一个思路;
.NET应用架构设计—面向查询服务的参数化查询设计(分解业务点,单独配置各自的数据查询契约)的更多相关文章
- App架构设计经验谈:服务端接口的设计
App与服务器的通信接口如何设计得好,需要考虑的地方挺多的,在此根据我的一些经验做一些总结分享,旨在抛砖引玉. 安全机制的设计 现在,大部分App的接口都采用RESTful架构,RESTFul最重要的 ...
- .NET应用架构设计—用户端的防腐层作用及设计
阅读目录: 1.背景介绍 2.SOA架构下的显示端架构腐化 3.有效使用防腐层来隔离碎片服务导致显示端逻辑腐烂 4.剥离服务调用的技术组件让其依赖接口 5.将服务的DTO与显示端的ViewModel之 ...
- MVC实用架构设计(三)——EF-Code First(4):数据查询
前言 首先对大家表示抱歉,这个系列已经将近一个月没有更新了,相信大家等本篇更新都等得快失望了.实在没办法,由于本人水平有限,写篇博客基本上要大半天的时间,最近实在是抽不出这么长段的空闲时间来写.另外也 ...
- 面向微服务的体系结构评审中需要问的三个问题-咖啡杂谈:Java、新闻、故事和观点
面向微服务的体系结构如今风靡全球.这是因为更快的部署节奏和更低的成本是面向微服务的体系结构的基本承诺. 然而,对于大多数试水的公司来说,开发活动更多的是将现有的单块应用程序转换为面向微服务的体系结构, ...
- MongoDB源码分析——mongod数据查询操作
源码版本为MongoDB 2.6分支 Edit mongod数据查询操作 在mongod的初始化过程中说过,服务端接收到客户端消息后调用MyMessageHandler::process函数处理消息. ...
- SharePoint服务器端对象模型 之 使用CAML进展数据查询
SharePoint服务器端对象模型 之 使用CAML进行数据查询 一.概述 在SharePoint的开发应用中,查询是非常常用的一种手段,根据某些筛选.排序条件,获得某个列表或者某一些列表中相应的列 ...
- 关系数据标准语言SQL之数据查询
数据查询是数据库的核心操作.SQL提供了SELECT语句进行数据查询,该语句具有灵活的使用方式和丰富的功能. 其一般格式为 select [all | distinct]<目标表达式>[, ...
- SQL - 数据查询
数据查询是数据库的核心操作.SQL 提供了 select 语句进行数据查询,该语句的一般格式为: select [ ALL | distinct ] <目标列表达式> [ ,<目 ...
- SQL数据查询之——单表查询
一.SQL数据查询的一般格式 数据查询是数据库的核心操作.SQL提供了SELECT语句进行数据查询,其一般格式为: SELECT [ALL | DISTINCT]<目标列表达式>[,< ...
随机推荐
- 【jQuery小实例】---2自定义动画
---本系列文章所用使用js均可在本博客文件中找到 本节用jQuery完一个简易的动画效果,一个小驴跑跑的效果.和一个类似qq面板效果.大致也分为三步:添加jquery-1.8.3.js文件.这个是不 ...
- WIFI网络操作
WIFI网卡状态(不可用状态值为1,正在关闭值为0,可用状态值为3,正在打开值为2) WIFI网卡状态是由一系列的整型常量表示,这一系列的整型常量都存储于WifiManager的类中 1.WIFI_S ...
- 【JavaScript】又一神器框架:linq.js
引言 前几天针对一个js数组交集的问题请教了下同事,他第一反应就是循环,这也是常规思路,因为我个人更倾向于js些,我便开玩笑,不知道js能不能像linq那样实现这些操作呢?果断百度了一把,果然有现成框 ...
- 百度eCharts体验
前言 从昨天开始给项目里添加一些图表对比功能,上一个项目里使用的是Highcharts,本打算继续用Highcharts做的,昨天试了下做出来的效果不太好,主要也是因为看的多了没什么新鲜感了,于是便尝 ...
- Android-Universal-Image-Loader 图片异步加载类库的使用
在博客中看到一篇利用组件进行图片异步加载的文章在此作记录 原文:http://blog.csdn.net/vipzjyno1/article/details/23206387 这个图片异步加载并缓存的 ...
- PopupWindow 点击外部和返回键无法消失背后的真相(setBackgroundDrawable(Drawable background))
刚接手PopupWindow的时候,我们都可能觉得很简单,因为它确实很简单,不过运气不好的可能就会踩到一个坑: 点击PopupWindow最外层布局以及点击返回键PopupWindow不会消失 新手在 ...
- Linux中解析json---jq
遇到要在Linux上处理json的请求,换了熟悉的环境就抓瞎了,需要用心学习基础知识. jq官网:https://stedolan.github.io/jq 1.install yum ins ...
- C# 利用socekt做到http监听,怎么样才能做到高性能
c#原始提供了http的监听的类HttpListener,实现了简单的http.文章地址<C# 控制台或者winform程序开启http的监听状态> 但是经过我测试,这个HttpListe ...
- Asp.Net Core 通过中间件防止图片盗链
一.原理 要实现防盗链,我们就必须先理解盗链的实现原理,提到防盗链的实现原理就不得不从HTTP协议说起,在HTTP协议中,有一个表头字段叫referer,采用URL的格式来表示从哪儿链接到当前的网页或 ...
- [AngularJS] AngularJS系列(6) 中级篇之ngResource
目录 $http ngResource $http几乎是所有ng开发中,都会用到的服务.本节将重点说下$http 与 ngResource $http 使用:$http(config); 参数: me ...
