好运飞艇app安卓架构师系列文:通过Spring Cloud组件Hystrix合并请求

  • 时间:
  • 浏览:0

    在前文里,亲戚亲戚亲们儿讲述了通过Hy好运飞艇app安卓S好运飞艇app安卓trix进行容错解决的方式 ,这里亲戚亲戚亲们儿将讲述通过Hystrix合并请求的方式

    哪怕有六个多URL请求调用的功能再简单,W好运飞艇app安卓好运飞艇app安卓eb应用服务都大慨会开启有六个线程来提供服务,换句话说,有效降低URL请求数能很大程度上降低系统的负载。通过Hystrix提供的“合并请求”机制,亲戚亲戚亲们儿能有效地降低请求数量。

    在如下的HystrixMerge好运飞艇app安卓Demo.java里,亲戚亲戚亲们儿将采集2秒内到达的所有“查询订单”的请求,并把它们合并到有六个多对象中传输给后台,后台则是根据多个请求参数统一返回查询结果,一点基于合并的做法将比每次只解决有六个多请求的方式 要高效得多,代码比较长,亲戚亲戚亲们儿按类来说明。    

1    //省略必要的package和import的代码
2    class OrderDetail{ //订单业务类,其中包富含六个多属性
3      private String orderId;
4      private String orderOwner;
5      //省略针对orderId和orderOwner的get和set方式


6          //重写toString方式

,方便输出
7          public String toString() {        
8            return "orderId: " + orderId + ", orderOwner: " + orderOwner ;
9          }
10    }
11    //合并订单请求的解决器
12    class OrderHystrixCollapser extends        HystrixCollapser<Map<String, OrderDetail>, OrderDetail, String> 
13    {
14        String orderId;
15        //在构造函数里传入请求参数
16        public OrderHystrixCollapser(String orderId) 
17    { this.orderId = orderId;}
18    //指定根据orderId去请求OrderDetail
19        public String getRequestArgument() 
20    { return orderId;    }
21    //创建请求命令
22        protected HystrixCommand<Map<String, OrderDetail>> createCommand(
23            Collection<CollapsedRequest<OrderDetail, String>> requests) 
24    { return new MergerCommand(requests); }
25        //把请求得到的结果和请求关联到一同
26        protected void mapResponseToRequests(Map<String, OrderDetail> batchResponse,
27            Collection<CollapsedRequest<OrderDetail, String>> requests) {
28            for (CollapsedRequest<OrderDetail, String> request : requests)    
29        {
80                // 请注意这里是得到单个请求的结果
31                OrderDetail oneOrderDetail = batchResponse.get(request.getArgument());
32                // 把结果关联到请求中
33                request.setResponse(oneOrderDetail);
34            }
35        }
36    }

    在第2行,亲戚亲戚亲们儿定义了OrderDetail类,这里,亲戚亲戚亲们儿将合并针对该类对象的请求。

    在第12行,亲戚亲戚亲们儿定义了合并订单的解决器OrderHystrixCollapser类, 它继承(extends)了HystrixCollapser<Map<String, OrderDetail>, OrderDetail, String>类,而HystrixCollapser泛型中富含了六个参数,其中第有六个多参数Map<String, OrderDetail>表示该合并解决器合并请求后返回的结果类型,第六个参数表示是合并OrderDetail类型的对象,第有六个多参数则表示是根据String类型的请求参数来合并对象。

    在第19行里,亲戚亲戚亲们儿指定了是根据String类型的OrderId参数来请求OrderDetail对象,在第22行的createCommand方式 里,亲戚亲戚亲们儿指定了是调用MergerCommand方式 来请求多个OrderDetail,在第26行的mapResponseToRequests方式 里,亲戚亲戚亲们儿是用第28行的for循环,依次把batchResponse对象中富含的多个的查询结果设置到request对象里,意味着request是参数requests里的元素,太久太久太久太久执行完第28行的for循环后,requests对象就能关联到合并后的查询结果。    

37    class MergerCommand extends HystrixCommand<Map<String, OrderDetail>> {
38        //用orderDB模拟数据库中的数据
39        static HashMap<String,String> orderDB = new HashMap<String,String> ();
40        static     {
41            orderDB.put("1","Peter");
42            orderDB.put("2","Tom");
43            orderDB.put("3","Mike");
44        }    
45        Collection<CollapsedRequest<OrderDetail, String>> requests;
46        public MergerCommand(Collection<CollapsedRequest<OrderDetail, String>> requests) {
47            super(Setter.withGroupKey(HystrixCommandGroupKey.Factory
48                    .asKey("mergeDemo")));
49            this.requests = requests;
80        }
51        //在run方式

里根据请求参数返回结果
52        protected Map<String, OrderDetail> run() throws Exception {
53            List<String> orderIds = new ArrayList<String>();
54            //通过for循环,整合参数
55            for(CollapsedRequest<OrderDetail, String> request : requests)    
56        { orderIds.add(request.getArgument());     }
57            // 调用服务,根据多个订单Id获得多个订单对象
58            Map<String, OrderDetail> ordersHM = getOrdersFromDB(orderIds);
59            return ordersHM;
80        }    
61        //用HashMap模拟数据库,从数据库中获得对象
62        private Map<String, OrderDetail> getOrdersFromDB(List<String> orderIds) {
63            Map<String, OrderDetail> result = new HashMap<String, OrderDetail>();
64            for(String orderId : orderIds) {
65                OrderDetail order = new OrderDetail();
66                //一点本该是从数据库里得到,但为了模拟,仅从HashMap里取数据
67                order.setOrderId(orderId);
68                order.setOrderOwner(orderDB.get(orderId) );            
69                result.put(orderId, order);
70            }
71            return result;
72        }
73    }

    在MergerCommand类的第38到44行里,亲戚亲戚亲们儿用了orderDB对象来模拟数据库里存储的订单数据。在第46行的构造函数里,亲戚亲戚亲们儿用传入的requests对象来构建本类里的同名对象,在一点传入的requests对象里,意味着富含了合并后的请求。

    在第52行的run方式 里,亲戚亲戚亲们儿通过第55行的for循环,依次遍历requests对象,并组装富含请求参数集合的orderIds对象,然后 在第58行里,通过getOrdersFromDB方式 ,根据List类型的orderIds参数,模拟地从数据库里读取数据。        

74    public class HystrixMergeDemo{
75        public static void main(String[] args){
76            // 采集2秒内占据

的请求,合并为有六个多命令执行
77            ConfigurationManager.getConfigInstance().setProperty(    "hystrix.collapser.default.timerDelayInMilliseconds", 800);
78            // 初始化请求上下文
79            HystrixRequestContext context = HystrixRequestContext    .initializeContext();
80            // 创建六个请求合并解决器
81            OrderHystrixCollapser collapser1 = new OrderHystrixCollapser("1");
82            OrderHystrixCollapser collapser2 = new OrderHystrixCollapser("2");
83            OrderHystrixCollapser collapser3 = new OrderHystrixCollapser("3");        
84            // 异步执行
85            Future<OrderDetail> future1 = collapser1.queue();
86            Future<OrderDetail> future2 = collapser2.queue();
87            Future<OrderDetail> future3 = collapser3.queue();        
88            try {
89                System.out.println(future1.get());
90                System.out.println(future2.get());
91                System.out.println(future3.get());
92            } catch (InterruptedException e) {
93                e.printStackTrace();
94            } catch (ExecutionException e) {
95                e.printStackTrace();
96            }
97            /关闭请求上下文
98            context.shutdown();
99        }
80    }

    第74行定义的HystrixMergeDemo类里富含着main方式 ,在第77行里,亲戚亲戚亲们儿设置了合并请求的窗口时间是2秒,在第81到83行,创建了六个合并解决器对象,从第85到87行,亲戚亲戚亲们儿是通过queue 方式 ,以异步的方式 启动了有六个多解决器,并在第89到91行里,输出了有六个多解决器返回的结果。一点线程的运行结果如下。     

1    orderId: 1, orderOwner: Peter
2    orderId: 2, orderOwner: Tom
3    orderId: 3, orderOwner: Mike

     实在 在main方式 里,亲戚亲戚亲们儿发起了3次调用,但意味着哪些调用是占据 在2秒内的,太久太久太久太久会被合并解决,下面亲戚亲戚亲们儿结合上述针对类和方式 的说明,归纳下合并解决六个请求的流程。

    步骤一,在代码的81到83行里,亲戚亲戚亲们儿是通过OrderHystrixCollapser类型的collapser1等有六个多对象来传入待合并解决的请求,OrderHystrixCollapser类会通过第16行的构造函数,分别接收有六个多对象传入的orderId参数,并通过第22行的createCommand方式 ,调用MergerCommand类的方式 执行“根据订单Id查订单”的业务。

    这里说明下,意味着在OrderHystrixCollapser内第16行的getRequestArgument方式 里,亲戚亲戚亲们儿指定了查询参数名是orderId,太久太久太久太久createCommand方式 的requests参数,会用orderId来设置查询请求,一同,MergerCommand类中的相关方式 也会用该对象来查询OrderDetail信息。

    步骤二,意味着在createCommand方式 里,调用了MergerCommand类的构造函数,太久太久太久太久会触发该类第52行的run方式 ,在一点方式 里,通过第55行和第56行的for循环,把request请求中富含的多个Argument(也太久太久太久太久OrderId)装进到orderIds一点List类型的对象中,然后 通过第58行的getOrdersFromDB方式 ,根据哪些orderIds去找对应的OrderDetail对象。

   步骤三,在getORdersFromDB方式 里,找到对应的多个OrderDetail对象,并组装成Map<String, OrderDetail>类型的result对象返回,否则按调用链的关系,层层返回给OrderHystrixCollapser类。

    步骤四,在OrderHystrixCollapser类的mapResponseToRequests方式 里,通过for循环,把多次请求的结果组装进requests对象中。意味着requests对象是Collection<CollapsedRequest<OrderDetail, String>>类型的,其中用String类型的OrderId关联到了有六个多OrderDetail对象,太久太久太久太久这里会把合并查询的结果再拆散给3次请求,具体而言,会把六个OrderDetail对象对应地返回给第85行到第87行通过queue调用的六个请求。

    这里请注意,实在 通过合并请求的解决方式 能降低URL请求的数量,但意味着合并后的URL请求数太久,会撑爆掉合并解决器(这里是OrderHystrixCollapser类)的缓存。比如在某项 目里,实在 只设置了合并5秒内的请求,但正好赶上秒杀活动,在一点窗口期内的请求数过万,如此 全是 意味着出大大问题。

    太久太久太久太久一般会在上线前,先通过测试选用合并解决器的缓存容量,然后 再预估下平均每秒的意味着访问数,否则再据此设置合并的窗口时间。

     此人 然后写的和本文有关的Spring Cloud其它相关文章。

  Hystrix针对不可用服务的保护机制以及引入缓存

 通过案例了解Hystrix的各种基本使用方式