基于leveldb的接口代理缓存策略

广告位招租
扫码页面底部二维码联系

在项目中有一个需求,当我们调试本地代码时【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。,不会直接在项目代码中去mock本地数据【版权所有】唐霜 www.tangshuang.net著作权归作者所有,禁止商业用途转载。,而是通过node的代理层去mock数据著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。。前端应用通过本地起的一个node服务代转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】理请求api接口,因此,在代理阶段,可以【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net对数据进行拦截,既可以对从远端返回的数据本文版权归作者所有,未经授权不得转载。本文作者:唐霜,转载请注明出处。进行修改后返回给前端应用,也可以在代理层原创内容,盗版必究。【原创不易,请尊重版权】面做一些优化,比如本文要讲到的缓存。

本文作者:唐霜,转载请注明出处。转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】

node代理【本文首发于唐霜的博客】

【版权所有】唐霜 www.tangshuang.net【本文受版权保护】【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】【本文首发于唐霜的博客】

node是非常轻量级的服务,特别适合用于【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。快速创建应用和后端服务的接入层。所谓接入转载请注明出处:www.tangshuang.net原创内容,盗版必究。层,除了进行数据处理外,其实更多时候是为原创内容,盗版必究。【访问 www.tangshuang.net 获取更多精彩内容】了解决在应用和后端接口之间,实现某些特殊原创内容,盗版必究。【本文首发于唐霜的博客】功能,例如打日志,例如对数据进行校验和校【关注微信公众号:wwwtangshuangnet】【本文受版权保护】正,例如在发生异常时对上下游服务进行信息未经授权,禁止复制转载。【本文首发于唐霜的博客】收集等等。而且node适合异步编程,在不转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】影响正常服务的情况下,还可以通过异步编程【本文受版权保护】【原创内容,转载请注明出处】,对某个动作后面的跟随动作做进一步的处理转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】

【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net

而常用的方案,就是利用node便捷的代理著作权归作者所有,禁止商业用途转载。原创内容,盗版必究。能力。node的http模块提供了便捷的著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。网络请求接口,基于此,中间件的node服【原创内容,转载请注明出处】转载请注明出处:www.tangshuang.net务编程模式被广泛应用。知名框架expre【转载请注明来源】【原创不易,请尊重版权】ss就是一个中间件的运作器,它的一切动作本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】都可以通过中间件机制实现。

【原创不易,请尊重版权】原创内容,盗版必究。【未经授权禁止转载】

【转载请注明来源】【本文受版权保护】【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】【本文受版权保护】

这种模式被广泛运用在现代框架编程中,一个转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。请求和响应被中间件兜住,并一层层的处理数本文作者:唐霜,转载请注明出处。【未经授权禁止转载】据。

本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。原创内容,盗版必究。

而要实现node代理,只需要一个代理中间【未经授权禁止转载】【本文首发于唐霜的博客】件即可。http-proxy-midde【原创不易,请尊重版权】本文作者:唐霜,转载请注明出处。lware这个包被广泛应用在这样的场景需【版权所有,侵权必究】【关注微信公众号:wwwtangshuangnet】求中。关于http-proxy-midd本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.netelware可以通过它的说明文档详细了解本文作者:唐霜,转载请注明出处。【版权所有,侵权必究】它的用法。通过http-proxy-mi本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。ddelware,我们可以让前端应用发来【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。的ajax请求转发到后端服务的api去,转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net在得到后端接口数据之后,通过代理又返回给【访问 www.tangshuang.net 获取更多精彩内容】未经授权,禁止复制转载。前端,这样做的一个好处是,可以在一个no【未经授权禁止转载】本文版权归作者所有,未经授权不得转载。de服务中同时提供接口和界面输出,解决跨【转载请注明来源】本文版权归作者所有,未经授权不得转载。域问题。

原创内容,盗版必究。【转载请注明来源】【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】

level数据库【原创内容,转载请注明出处】

【原创内容,转载请注明出处】【作者:唐霜】本文作者:唐霜,转载请注明出处。原创内容,盗版必究。

leveldb在我之前的文章中已经介绍过未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。了,这里正好是它发挥作用的实用场景。为什【关注微信公众号:wwwtangshuangnet】【关注微信公众号:wwwtangshuangnet】么要选择leveldb,而非redis这【原创不易,请尊重版权】原创内容,盗版必究。样更知名的kv数据库?有两个原因,一是r【转载请注明来源】【本文首发于唐霜的博客】edis需要另外安装和启动服务,而lev转载请注明出处:www.tangshuang.net原创内容,盗版必究。el不需要,通过npm安装后会自动编译在【作者:唐霜】【未经授权禁止转载】本地,甚至可以通过打包level目录共享【访问 www.tangshuang.net 获取更多精彩内容】【关注微信公众号:wwwtangshuangnet】数据,二是level提供了超级方便的ap【版权所有,侵权必究】【本文首发于唐霜的博客】i进行操作,对于开端开发者而言,简直无需【关注微信公众号:wwwtangshuangnet】【本文受版权保护】学习(和localStorage极其相似【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。)。

【本文受版权保护】【版权所有,侵权必究】原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】

但是leveldb只能存取基础类型数据,【本文首发于唐霜的博客】【访问 www.tangshuang.net 获取更多精彩内容】而不能存对象,因此,还需要做一层封装。今天在看文档时,发现实际上leveldb【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】是支持直接存储对象的。恰巧,我所开发的h【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。ello-storage可以帮助我们瞬间【本文首发于唐霜的博客】【原创不易,请尊重版权】解决这个问题。

转载请注明出处:www.tangshuang.net【原创不易,请尊重版权】【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。
const { HelloStorage } = require('hello-storage');
const level = require('level');

const ldb = level('leveldb');
const ldbSotrage = {
	getItem: key => ldb.get(key).catch(() => null),
	setItem: (key, value) => ldb.put(key, value),
	removeItem: key => ldb.del(key)
};
const store = new HelloStorage({
	storage: ldbSotrage,
	stringify: false,
	async: true
});

可以看到,整个过程非常方便,这样,就可以著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。让leveldb支持对象以及支持过期时间【版权所有】唐霜 www.tangshuang.net【关注微信公众号:wwwtangshuangnet】等能力。

【本文首发于唐霜的博客】【原创不易,请尊重版权】本文版权归作者所有,未经授权不得转载。

请求唯一性转载请注明出处:www.tangshuang.net

【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。未经授权,禁止复制转载。【本文首发于唐霜的博客】

kv数据库的特点是,key值一定要唯一。未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net而我们前端发出去的请求,即使同一个资源,著作权归作者所有,禁止商业用途转载。著作权归作者所有,禁止商业用途转载。也有可能会通过传一些特别的参数而不同,要著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net解决这个问题,我们可以通过使用一些方法,【本文受版权保护】【关注微信公众号:wwwtangshuangnet】使每一个请求,都能得到一个唯一的hash【未经授权禁止转载】【原创内容,转载请注明出处】

【本文受版权保护】【原创不易,请尊重版权】【作者:唐霜】未经授权,禁止复制转载。
const queryString = require('query-string');
const { getObjectHashcode } = require('object-hashcode');

function handle(req, res, next) {
		const url = URL.parse(req.originalUrl);
		const { pathname, query } = url;
		const search = Object.assign({}, queryString.parse(query));
		
		// 删除不需要的参数
		delete search.request_id;

		const hash = getObjectHashcode({ pathname, search });

		store.get(hash).then((data) => {
			if (!data) {
				next();
			}
			else {
				let output = JSON.stringify(data);
				res.setHeader('Content-Type', 'application/json; charset=utf-8');
				res.end(output);
			}
		});
	}
}

通过求一个hash,保证了请求对应的唯一未经授权,禁止复制转载。本文版权归作者所有,未经授权不得转载。性。

著作权归作者所有,禁止商业用途转载。【版权所有,侵权必究】本文版权归作者所有,未经授权不得转载。【作者:唐霜】

代理缓存【转载请注明来源】

本文版权归作者所有,未经授权不得转载。【作者:唐霜】转载请注明出处:www.tangshuang.net本文作者:唐霜,转载请注明出处。【未经授权禁止转载】

在上一段代码中,我们创建了一个handl原创内容,盗版必究。【原创内容,转载请注明出处】e函数,而这个handle函数,就是一个【原创不易,请尊重版权】【未经授权禁止转载】中间件,可以结合各类基于http模块开发本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。的框架使用(中间件机制由框架实现,而非h未经授权,禁止复制转载。【本文受版权保护】ttp模块本身)。

【关注微信公众号:wwwtangshuangnet】【未经授权禁止转载】【版权所有,侵权必究】转载请注明出处:www.tangshuang.net原创内容,盗版必究。

根据中间件机制的特点,中间件的执行和拦截【本文首发于唐霜的博客】【未经授权禁止转载】是有一定顺序的,通过next函数来控制,【作者:唐霜】【本文受版权保护】因此我们需要在中间件序列中合理安排顺序。著作权归作者所有,禁止商业用途转载。本文作者:唐霜,转载请注明出处。当一个请求进来之后,先被handle函数原创内容,盗版必究。原创内容,盗版必究。兜住,如果next函数被执行,那么就进入【转载请注明来源】本文作者:唐霜,转载请注明出处。代理中间件(http-proxy-mid【未经授权禁止转载】未经授权,禁止复制转载。dleware)进行处理。我们在代理的响【作者:唐霜】【本文受版权保护】应接收阶段记录缓存。

【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。转载请注明出处:www.tangshuang.net
	onProxyRes(proxyRes, req, res) {
			const url = URL.parse(req.originalUrl);
			const { pathname, query } = url;
			const search = Object.assign({}, queryString.parse(query));
			
			// 删除不需要的参数
			delete search.request_id;

			const hash = getObjectHashcode({ pathname, search });

			const ret = [];
			proxyRes.on('data', (chunk) => {
				ret.push(chunk.toString());
			});
			proxyRes.on('end', () => {
				let json = ret.join('');
				try {
					let data = JSON.parse(json);
					if (!data.error) {
						store.set(hash, data);
					}
				}
				catch(e) {
					console.error(e);
				}
			});
		}
	}),

在数据返回后,将它作为缓存保存起来。但是【版权所有】唐霜 www.tangshuang.net本文版权归作者所有,未经授权不得转载。由于整个操作是异步的,因此,并不影响数据【访问 www.tangshuang.net 获取更多精彩内容】本文作者:唐霜,转载请注明出处。直接输出给前端的性能。

【作者:唐霜】转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】

小结【版权所有】唐霜 www.tangshuang.net

【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net本文版权归作者所有,未经授权不得转载。【本文受版权保护】

代理模式是开发中常用的模式,把它运用到实【未经授权禁止转载】未经授权,禁止复制转载。际开发过程中,也是非常的有趣。之前一直在【作者:唐霜】本文版权归作者所有,未经授权不得转载。介绍leveldb,算是一个狂热粉,这次【本文受版权保护】本文版权归作者所有,未经授权不得转载。正好通过本文把它运用到实际工作中。除了上【版权所有】唐霜 www.tangshuang.net【作者:唐霜】文提到的这些点外,你还可以在中间件思想的本文版权归作者所有,未经授权不得转载。著作权归作者所有,禁止商业用途转载。基础上继续添加,达到你想要的功能。另外,原创内容,盗版必究。【未经授权禁止转载】上面的整个过程中,没有配置一个缓存的快关【关注微信公众号:wwwtangshuangnet】本文版权归作者所有,未经授权不得转载。和过期时间,这也是一个需要完善的地方。

【版权所有】唐霜 www.tangshuang.net【本文受版权保护】【关注微信公众号:wwwtangshuangnet】转载请注明出处:www.tangshuang.net

2019-01-31 4290 , ,

为价值买单,打赏一杯咖啡

本文价值42.9RMB