数据库调优
2019-11-16 15:35:24摘要:影响性能因素 * 数据库结构设计 * T-SQL语句 * 数据量大 * 事务和隔离级别 * 硬件资源 * IO阻塞 * 批量删除表数据:大量删除时会记录到日志中,也会造成IO阻塞 阅读全文
摘要:影响性能因素 * 数据库结构设计 * T-SQL语句 * 数据量大 * 事务和隔离级别 * 硬件资源 * IO阻塞 * 批量删除表数据:大量删除时会记录到日志中,也会造成IO阻塞 阅读全文
摘要:需求背景 假设,你正在参与开发一个微服务。微服务通过 HTTP 协议暴露接口给其他系统调用,说直白点就是,其他系统通过 URL 来调用微服务的接口。有一天,你的 leader 找到你说,“为了保证接口调用的安全性,我们希望设计实现一个接口调用鉴权功能,只有经过认证之后的系统才能调用我们的接口,没有认证过的系统调用我们的接口会被拒绝。我希望由你来负责这个任务的开发,争取尽快上线。” 需求分析 1. 第一轮基础分析 对于如何做鉴权这样一个问题,最简单的解决方案就是,通过用户名加密码来做认证。我们给每个允许访问我们服务的调用方,派发一个应用名(或者叫应用 ID、AppID)和一个对应的密码(或者叫秘钥)。调用方每次进行接口请求的时候,都携带自己的 AppID 和密码。微服务在接收到接口调用请求之后,会解析出 AppID 和密码,跟存储在微服务端的 AppID 和密码进行比对。如果一致,说明认证成功,则允许接口调用请求;否则,就拒绝接口调用请求。 2. 第二轮分析优化 不过,这样的验证方式,每次都要明文传输密码。密码很容易被截获,是不安全的。那如果我们借助加密算法(比如 SHA),对密码进行加密之后,再传递到微服务端验证,是不是就可以了呢?实际上,这样也是不安全的,因为加密之后的密码及 AppID,照样可以被未认证系统(或者说黑客)截获,未认证系统可以携带这个加密之后的密码以及对应的 AppID,伪装成已认证系统来访问我们的接口。 这就是典型的“重放攻击” 。 提出问题,然后再解决问题,是一个非常好的迭代优化方法。对于这个问题,我们可以借助 OAuth 的验证思路来解决。调用方将请求接口的 URL 跟 AppID、密码拼接在一起,然后进行加密,生成一个 token。调用方在进行接口请求的的时候,将这个 token 及 AppID,随 URL 一块传递给微服务端。微服务端接收到这些数据之后,根据 AppID 从数据库中取出对应的密码,并通过同样的 token 生成算法,生成另外一个 token。用这个新生成的 token 跟调用方传递过来的 token 对比。如果一致,则允许接口调用请求;否则,就拒绝接口调用请求。 3. 第三轮分析优化 不过,这样的设计仍然存在重放攻击的风险,还是不够安全。每个 URL 拼接上 AppID、密码生成的 token 都是固定的。未认证系统截…… 阅读全文
摘要:1. 目标 如下代码:我们要实现缓存,但希望让使用者不用关心缓存的具体实现,只需要使用者在要操作缓存的方法上加上特性标注即可。 [Caching(CachingMethod.Remove, GetLinksQuery)] public class CreateLinkCommand { } [Caching(CachingMethod.Get)] public class GetLinksQuery : IRequestListLinkViewModel { } 要实现我们的目标,我们把任务分成2部分,首先实现缓存逻辑,然后将缓存基于特性做AOP实现。 2. 缓存实现 首先我们定义一个缓存接口 public interface ICacheProvider { /// summary /// 向缓存中添加一个对象。 /// /summary /// param name=key缓存的键值,该值通常是使用缓存机制的方法的名称。/param /// param name=valKey缓存值的键值,该值通常是由使用缓存机制的方法的参数值所产生。/param /// param name=value需要缓存的对象。/param void Add(string key, string valKey, object value); void Put(string key, string valKey, object value); object Get(string key, string valKey); void Remove(string key); bool Exists(string key); bool Exists(string key, string valKey); } 如上代码,为什么接口中key和valKey2个参数呢?这是因为我们可能会缓存同一个方法不同参数的结果,如在一个获取分页结果的方法中,我们可能会返回不同页的结果。如我们目标中GetLinksQuery方法缓存的值会是一个分页显示结果的字典。key是我们缓存的方法名,valKey这是缓存的字典结果中的字典key,value则是字典的结果。要进一步理解可以查看下面基于内存的…… 阅读全文
摘要:源码 /* ******************************************************************* */ /* CSS FUNCTIONS */ /* ******************************************************************* */ var CSS = (function() { var css = {}; // 转换的RGB字符串的形式“的RGB ( 255 , 255 , 255 ) ”到“ #ffffff ” css.rgb2hex = function(rgbString) { if (typeof (rgbString) != string || !defined(rgbString.match)) { return null; } var result = rgbString.match(/^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*/); if (result == null) { return rgbString; } var rgb = +result[1] 16 | +result[2] 8 | +result[3]; var hex = ; var digits = 0123456789abcdef; while (rgb != 0) { hex = digits.charAt(rgb 0xf) + hex; rgb = 4; } while (hex.length 6) { hex = '0' + hex; } return # + hex; }; // 转换字符样式 css.hyphen2camel = function(property) { if (!defined(property) |…… 阅读全文
摘要:源码 /* ******************************************************************* */ /* EVENT FUNCTIONS */ /* ******************************************************************* */ var Event = (function() { var ev = {}; //阻止事件冒泡 ev.stopBubble = function(e) { // 如果传入了事件对象,那么就是非IE浏览器 if (e) // 因此它支持W3C的stopPropagation e.stopPropagation(); else // 否则,我们得使用IE的方式取消事件冒泡 window.event.cancelBubble = true; }; //防止发生默认浏览器行为 ev.stopDefault = function(e) { // 防止默认浏览器行为(W3C) if (e) e.preventDefault(); // IE中防止浏览器行为的捷径 return false; }; // // 由 Dean Edwards 所编写的addEvent/removeEvent 2005 // 由Tino Zijdel整理 // http://dean.edwards.name/weblog/2005/10/add-event/ ev.addEvent = function(element, type, handler) { //为每个事件处理函数赋予一个独立的ID if (!handler.$$guid) handler.$$guid = ev.addEvent.guid++; …… 阅读全文
摘要:源码 /* ******************************************************************* */ /* DOM FUNCTIONS */ /* ******************************************************************* */ var DOM = (function() { var dom = {}; //查找相关元素的前兄弟元素 dom.prev = function(elem) { do { elem = elem.previousSibling; } while (elem elem.nodeType != 1); return elem; }; //查找相关元素的后兄弟元素 dom.next = function(elem) { do { elem = elem.nextSibling; } while (elem elem.nodeType != 1); return elem; }; //查找第一个子元素 dom.first = function(elem) { elem = elem.firstChild; return elem elem.nodeType != 1 ? nextSibling(elem) : elem; }; //查找最后一个子元素 dom.last = function(elem) { elem = elem.lastChild; return elem elem.nodeType != 1 ? prevSibling(elem) : elem; }; //查找父元素 dom.parent = function(elem, num) { num…… 阅读全文
摘要:源码 /** * Copyright (c)2008 xiaosuo */ /* ******************************************************************* */ /* UTIL FUNCTIONS */ /* ******************************************************************* */ var Util = { 'VERSION':1.1 }; //获取id function id(name) { return document.getElementById(name); } //获取指定元素 function tag(name, elem) { // 如果不提供上下文元素,则遍历整个文档 return (elem || document).getElementsByTagName(name); } //判断对象是否存在 function defined(o) { return (typeof (o) != undefined); } /* ******************************************************************* */ /* OBJECT FUNCTIONS */ /* ******************************************************************* */ var Obj = (function() { var object = {}; //检查是否是对象 object.isObject = function(o) { return (o != null typeof (o) == object defined(o.constructor) o.constructor == Object !defined(o.node…… 阅读全文