vue获取商品数据接口_基于 request cache 请求缓存技术优化批量商品数据查询接口...
Hystrix command 執(zhí)行時 8 大步驟第三步,就是檢查 Request cache 是否有緩存。
首先,有一個概念,叫做 Request Context 請求上下文,一般來說,在一個 web 應用中,如果我們用到了 Hystrix,我們會在一個 filter 里面,對每一個請求都施加一個請求上下文。就是說,每一次請求,就是一次請求上下文。然后在這次請求上下文中,我們會去執(zhí)行 N 多代碼,調(diào)用 N 多依賴服務,有的依賴服務可能還會調(diào)用好幾次。
在一次請求上下文中,如果有多個 command,參數(shù)都是一樣的,調(diào)用的接口也是一樣的,而結(jié)果可以認為也是一樣的。那么這個時候,我們可以讓第一個 command 執(zhí)行返回的結(jié)果緩存在內(nèi)存中,然后這個請求上下文后續(xù)的其它對這個依賴的調(diào)用全部從內(nèi)存中取出緩存結(jié)果就可以了。
這樣的話,好處在于不用在一次請求上下文中反復多次執(zhí)行一樣的 command,避免重復執(zhí)行網(wǎng)絡請求,提升整個請求的性能。
舉個栗子。比如說我們在一次請求上下文中,請求獲取 productId 為 1 的數(shù)據(jù),第一次緩存中沒有,那么會從商品服務中獲取數(shù)據(jù),返回最新數(shù)據(jù)結(jié)果,同時將數(shù)據(jù)緩存在內(nèi)存中。后續(xù)同一次請求上下文中,如果還有獲取 productId 為 1 的數(shù)據(jù)的請求,直接從緩存中取就好了。
HystrixCommand 和 HystrixObservableCommand 都可以指定一個緩存 key,然后 Hystrix 會自動進行緩存,接著在同一個 request context 內(nèi),再次訪問的話,就會直接取用緩存。
下面,我們結(jié)合一個具體的業(yè)務場景,來看一下如何使用 request cache 請求緩存技術。當然,以下代碼只作為一個基本的 Demo 而已。
現(xiàn)在,假設我們要做一個批量查詢商品數(shù)據(jù)的接口,在這個里面,我們是用 HystrixCommand 一次性批量查詢多個商品 id 的數(shù)據(jù)。但是這里有個問題,如果說 Nginx 在本地緩存失效了,重新獲取一批緩存,傳遞過來的 productIds 都沒有進行去重,比如 productIds=1,1,1,2,2,那么可能說,商品 id 出現(xiàn)了重復,如果按照我們之前的業(yè)務邏輯,可能就會重復對 productId=1 的商品查詢?nèi)?#xff0c;productId=2 的商品查詢兩次。
我們對批量查詢商品數(shù)據(jù)的接口,可以用 request cache 做一個優(yōu)化,就是說一次請求,就是一次 request context,對相同的商品查詢只執(zhí)行一次,其余重復的都走 request cache。
實現(xiàn) Hystrix 請求上下文過濾器并注冊
定義 HystrixRequestContextFilter 類,實現(xiàn) Filter 接口。
/** * Hystrix 請求上下文過濾器 */public class HystrixRequestContextFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) { HystrixRequestContext context = HystrixRequestContext.initializeContext(); try { filterChain.doFilter(servletRequest, servletResponse); } catch (IOException | ServletException e) { e.printStackTrace(); } finally { context.shutdown(); } } @Override public void destroy() { }}然后將該 filter 對象注冊到 SpringBoot Application 中。
@SpringBootApplicationpublic class EshopApplication { public static void main(String[] args) { SpringApplication.run(EshopApplication.class, args); } @Bean public FilterRegistrationBean filterRegistrationBean() { FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new HystrixRequestContextFilter()); filterRegistrationBean.addUrlPatterns("/*"); return filterRegistrationBean; }}command 重寫 getCacheKey() 方法
在 GetProductInfoCommand 中,重寫 getCacheKey() 方法,這樣的話,每一次請求的結(jié)果,都會放在 Hystrix 請求上下文中。下一次同一個 productId 的數(shù)據(jù)請求,直接取緩存,無須再調(diào)用 run() 方法。
public class GetProductInfoCommand extends HystrixCommand { private Long productId; private static final HystrixCommandKey KEY = HystrixCommandKey.Factory.asKey("GetProductInfoCommand"); public GetProductInfoCommand(Long productId) { super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("ProductInfoService")) .andCommandKey(KEY)); this.productId = productId; } @Override protected ProductInfo run() { String url = "http://localhost:8081/getProductInfo?productId=" + productId; String response = HttpClientUtils.sendGetRequest(url); System.out.println("調(diào)用接口查詢商品數(shù)據(jù),productId=" + productId); return JSONObject.parseObject(response, ProductInfo.class); } /** * 每次請求的結(jié)果,都會放在Hystrix綁定的請求上下文上 * * @return cacheKey 緩存key */ @Override public String getCacheKey() { return "product_info_" + productId; } /** * 將某個商品id的緩存清空 * * @param productId 商品id */ public static void flushCache(Long productId) { HystrixRequestCache.getInstance(KEY, HystrixConcurrencyStrategyDefault.getInstance()).clear("product_info_" + productId); }}這里寫了一個 flushCache() 方法,用于我們開發(fā)手動刪除緩存。
controller 調(diào)用 command 查詢商品信息
在一次 web 請求上下文中,傳入商品 id 列表,查詢多條商品數(shù)據(jù)信息。對于每個 productId,都創(chuàng)建一個 command。
如果 id 列表沒有去重,那么重復的 id,第二次查詢的時候就會直接走緩存。
@Controllerpublic class CacheController { /** * 一次性批量查詢多條商品數(shù)據(jù)的請求 * * @param productIds 以,分隔的商品id列表 * @return 響應狀態(tài) */ @RequestMapping("/getProductInfos") @ResponseBody public String getProductInfos(String productIds) { for (String productId : productIds.split(總結(jié)
以上是生活随笔為你收集整理的vue获取商品数据接口_基于 request cache 请求缓存技术优化批量商品数据查询接口...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mysql无法初始化数据库引擎_mysq
- 下一篇: 条件渲染vue