brave本身没有对AsyncHttpClient提供类似于brave-okhttp的ClientRequestInterceptor和ClientResponseInterceptor,所以需要我们定制,而ServerRequestInterceptor和ServerResponseInterceptor是在BraveServletFilter部分直接指定就好了(这在任何client技术下都可以复用)。

实际上,ClientRequestInterceptor和ClientResponseInterceptor也是我们的定制点

一、代码

基本参考第二十七章 springboot + zipkin(brave-okhttp实现)

1、service1

1.1、pom.xml

 1 <!-- zipkin brave -->
 2         <dependency>
 3             <groupId>io.zipkin.brave</groupId>
 4             <artifactId>brave-core</artifactId>
 5             <version>3.9.0</version>
 6         </dependency>
 7         <dependency>
 8             <groupId>io.zipkin.brave</groupId>
 9             <artifactId>brave-spancollector-http</artifactId>
10             <version>3.9.0</version>
11         </dependency>
12         <dependency>
13             <groupId>io.zipkin.brave</groupId>
14             <artifactId>brave-web-servlet-filter</artifactId>
15             <version>3.9.0</version>
16         </dependency>
17         <!-- async-http-client -->
18         <dependency>
19             <groupId>com.ning</groupId>
20             <artifactId>async-http-client</artifactId>
21             <version>1.9.31</version>
22         </dependency>

View Code

1.2、ZipkinConfig

 1 package com.xxx.service1.zipkin.brave.async;
 2
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5
 6 import com.github.kristofa.brave.Brave;
 7 import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler;
 8 import com.github.kristofa.brave.Sampler;
 9 import com.github.kristofa.brave.SpanCollector;
10 import com.github.kristofa.brave.http.DefaultSpanNameProvider;
11 import com.github.kristofa.brave.http.HttpSpanCollector;
12 import com.github.kristofa.brave.servlet.BraveServletFilter;
13 import com.ning.http.client.AsyncHttpClient;
14
15 @Configuration
16 public class ZipkinConfig {
17     @Bean
18     public SpanCollector spanCollector() {
19         HttpSpanCollector.Config spanConfig = HttpSpanCollector.Config.builder()
20                                               .compressionEnabled(false)//默认false,span在transport之前是否会被gzipped。
21                                               .connectTimeout(5000)//5s,默认10s
22                                               .flushInterval(1)//1s
23                                               .readTimeout(6000)//5s,默认60s
24                                               .build();
25         return HttpSpanCollector.create("http://localhost:9411",
26                                         spanConfig,
27                                         new EmptySpanCollectorMetricsHandler());
28     }
29
30     @Bean
31     public Brave brave(SpanCollector spanCollector) {
32         Brave.Builder builder = new Brave.Builder("asyn1 - service1 - 1");//指定serviceName
33         builder.spanCollector(spanCollector);
34         builder.traceSampler(Sampler.create(1));//采集率
35         return builder.build();
36     }
37
38     @Bean
39     public BraveServletFilter braveServletFilter(Brave brave) {
40         /**
41          * 设置sr、ss拦截器
42          */
43         return new BraveServletFilter(brave.serverRequestInterceptor(),
44                                       brave.serverResponseInterceptor(),
45                                       new DefaultSpanNameProvider());
46     }
47
48     @Bean
49     public AsyncHttpClient asyncHttpClient(){
50         return new AsyncHttpClient();
51     }
52 }

View Code

说明:指定了serviceName:"asyn1 - service1 - 1"

1.3、ZipkinAsyncController

 1 package com.xxx.service1.zipkin.brave.async;
 2
 3 import java.net.URI;
 4 import java.util.concurrent.Future;
 5
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.web.bind.annotation.RequestMapping;
 8 import org.springframework.web.bind.annotation.RequestMethod;
 9 import org.springframework.web.bind.annotation.RestController;
10
11 import com.github.kristofa.brave.Brave;
12 import com.github.kristofa.brave.http.DefaultSpanNameProvider;
13 import com.github.kristofa.brave.http.HttpClientRequest;
14 import com.github.kristofa.brave.http.HttpClientRequestAdapter;
15 import com.github.kristofa.brave.http.HttpClientResponseAdapter;
16 import com.github.kristofa.brave.http.HttpResponse;
17 import com.ning.http.client.AsyncHttpClient;
18 import com.ning.http.client.Request;
19 import com.ning.http.client.RequestBuilder;
20 import com.ning.http.client.Response;
21
22 import io.swagger.annotations.Api;
23 import io.swagger.annotations.ApiOperation;
24
25 @Api("zipkin brave async api")
26 @RestController
27 @RequestMapping("/zipkin/async/service1")
28 public class ZipkinAsyncController {
29
30     @Autowired
31     private AsyncHttpClient asyncHttpClient;
32     @Autowired
33     private Brave           brave;
34
35     @ApiOperation("trace第一步")
36     @RequestMapping(value = "/test1", method = RequestMethod.GET)
37     public String myboot() {
38
39         try {
40             RequestBuilder builder = new RequestBuilder();
41             String url = "http://localhost:8032/zipkin/async/service2/test2";
42             builder.setUrl(url);
43             Request request = builder.build();
44
45             clientRequestInterceptor(request);
46             Future<Response> response = asyncHttpClient.executeRequest(request);
47             clientResponseInterceptor(response.get());
48
49             return response.get().getResponseBody();
50         } catch (Exception e) {
51             e.printStackTrace();
52             return "";
53         }
54     }
55
56     private void clientRequestInterceptor(Request request) {
57         brave.clientRequestInterceptor().handle(new HttpClientRequestAdapter(new HttpClientRequest() {
58
59             @Override
60             public URI getUri() {
61                 return URI.create(request.getUrl());
62             }
63
64             @Override
65             public String getHttpMethod() {
66                 return request.getMethod();
67             }
68
69             @Override
70             public void addHeader(String headerKey, String headerValue) {
71                 request.getHeaders().add(headerKey, headerValue);
72             }
73         }, new DefaultSpanNameProvider()));
74     }
75
76     private void clientResponseInterceptor(Response response) {
77         brave.clientResponseInterceptor().handle(new HttpClientResponseAdapter(new HttpResponse() {
78             public int getHttpStatusCode() {
79                 return response.getStatusCode();
80             }
81         }));
82     }
83
84 }

View Code

说明:

  • clientRequestInterceptor(com.ning.http.client.Request request)

    • 其实就是在做cs
  • clientResponseInterceptor(com.ning.http.client.Response response)
    • 其实就是在做cr

2、service2

2.1、pom.xml

 1 <!-- zipkin brave -->
 2         <dependency>
 3             <groupId>io.zipkin.brave</groupId>
 4             <artifactId>brave-core</artifactId>
 5             <version>3.9.0</version>
 6         </dependency>
 7         <dependency>
 8             <groupId>io.zipkin.brave</groupId>
 9             <artifactId>brave-spancollector-http</artifactId>
10             <version>3.9.0</version>
11         </dependency>
12         <dependency>
13             <groupId>io.zipkin.brave</groupId>
14             <artifactId>brave-web-servlet-filter</artifactId>
15             <version>3.9.0</version>
16         </dependency>
17         <!-- async-http-client -->
18         <dependency>
19             <groupId>com.ning</groupId>
20             <artifactId>async-http-client</artifactId>
21             <version>1.9.31</version>
22         </dependency>

View Code

2.2、ZipkinConfig

 1 package com.xxx.service1.zipkin.brave.async;
 2
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5
 6 import com.github.kristofa.brave.Brave;
 7 import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler;
 8 import com.github.kristofa.brave.Sampler;
 9 import com.github.kristofa.brave.SpanCollector;
10 import com.github.kristofa.brave.http.DefaultSpanNameProvider;
11 import com.github.kristofa.brave.http.HttpSpanCollector;
12 import com.github.kristofa.brave.servlet.BraveServletFilter;
13 import com.ning.http.client.AsyncHttpClient;
14
15 @Configuration
16 public class ZipkinConfig {
17     @Bean
18     public SpanCollector spanCollector() {
19         HttpSpanCollector.Config spanConfig = HttpSpanCollector.Config.builder()
20                                               .compressionEnabled(false)//默认false,span在transport之前是否会被gzipped。
21                                               .connectTimeout(5000)//5s,默认10s
22                                               .flushInterval(1)//1s
23                                               .readTimeout(6000)//5s,默认60s
24                                               .build();
25         return HttpSpanCollector.create("http://localhost:9411",
26                                         spanConfig,
27                                         new EmptySpanCollectorMetricsHandler());
28     }
29
30     @Bean
31     public Brave brave(SpanCollector spanCollector) {
32         Brave.Builder builder = new Brave.Builder("asyn2 - service2 - 2");//指定serviceName
33         builder.spanCollector(spanCollector);
34         builder.traceSampler(Sampler.create(1));//采集率
35         return builder.build();
36     }
37
38     @Bean
39     public BraveServletFilter braveServletFilter(Brave brave) {
40         /**
41          * 设置sr、ss拦截器
42          */
43         return new BraveServletFilter(brave.serverRequestInterceptor(),
44                                       brave.serverResponseInterceptor(),
45                                       new DefaultSpanNameProvider());
46     }
47
48     @Bean
49     public AsyncHttpClient asyncHttpClient(){
50         return new AsyncHttpClient();
51     }
52 }

View Code

说明:指定了serviceName:"asyn2 - service2 - 2"

2.3、ZipkinAsyncController

 1 package com.xxx.service2.zipkin.brave.async;
 2
 3 import java.net.URI;
 4 import java.util.concurrent.Future;
 5
 6 import org.springframework.beans.factory.annotation.Autowired;
 7 import org.springframework.web.bind.annotation.RequestMapping;
 8 import org.springframework.web.bind.annotation.RequestMethod;
 9 import org.springframework.web.bind.annotation.RestController;
10
11 import com.github.kristofa.brave.Brave;
12 import com.github.kristofa.brave.http.DefaultSpanNameProvider;
13 import com.github.kristofa.brave.http.HttpClientRequest;
14 import com.github.kristofa.brave.http.HttpClientRequestAdapter;
15 import com.github.kristofa.brave.http.HttpClientResponseAdapter;
16 import com.github.kristofa.brave.http.HttpResponse;
17 import com.ning.http.client.AsyncHttpClient;
18 import com.ning.http.client.Request;
19 import com.ning.http.client.RequestBuilder;
20 import com.ning.http.client.Response;
21
22 import io.swagger.annotations.Api;
23 import io.swagger.annotations.ApiOperation;
24
25 @Api("zipkin brave async api")
26 @RestController
27 @RequestMapping("/zipkin/async/service2")
28 public class ZipkinAsyncController {
29
30     @Autowired
31     private AsyncHttpClient asyncHttpClient;
32     @Autowired
33     private Brave           brave;
34
35     @ApiOperation("trace第2步")
36     @RequestMapping(value = "/test2", method = RequestMethod.GET)
37     public String myboot2() {
38
39         try {
40             /*****************************serivce3*******************************/
41             RequestBuilder builder3 = new RequestBuilder();
42             String url3 = "http://localhost:8033/zipkin/async/service3/test3";
43             builder3.setUrl(url3);
44             Request request3 = builder3.build();
45
46             clientRequestInterceptor(request3);
47             Future<Response> response3 = asyncHttpClient.executeRequest(request3);
48             clientResponseInterceptor(response3.get());
49
50             /*****************************serivce4*******************************/
51             RequestBuilder builder4 = new RequestBuilder();
52             String url4 = "http://localhost:8034/zipkin/async/service4/test4";
53             builder4.setUrl(url4);
54             Request request4 = builder4.build();
55
56             clientRequestInterceptor(request4);
57             Future<Response> response4 = asyncHttpClient.executeRequest(request4);
58             clientResponseInterceptor(response4.get());
59
60             return response3.get().getResponseBody() + "=====" + response4.get().getResponseBody();
61         } catch (Exception e) {
62             e.printStackTrace();
63             return "";
64         }
65     }
66
67     private void clientRequestInterceptor(Request request) {
68         brave.clientRequestInterceptor().handle(new HttpClientRequestAdapter(new HttpClientRequest() {
69
70             @Override
71             public URI getUri() {
72                 return URI.create(request.getUrl());
73             }
74
75             @Override
76             public String getHttpMethod() {
77                 return request.getMethod();
78             }
79
80             @Override
81             public void addHeader(String headerKey, String headerValue) {
82                 request.getHeaders().add(headerKey, headerValue);
83             }
84         }, new DefaultSpanNameProvider()));
85     }
86
87     private void clientResponseInterceptor(Response response) {
88         brave.clientResponseInterceptor().handle(new HttpClientResponseAdapter(new HttpResponse() {
89             public int getHttpStatusCode() {
90                 return response.getStatusCode();
91             }
92         }));
93     }
94
95 }

View Code

3、service3

3.1、pom.xml

 1 <!-- zipkin brave -->
 2         <dependency>
 3             <groupId>io.zipkin.brave</groupId>
 4             <artifactId>brave-core</artifactId>
 5             <version>3.9.0</version>
 6         </dependency>
 7         <dependency>
 8             <groupId>io.zipkin.brave</groupId>
 9             <artifactId>brave-spancollector-http</artifactId>
10             <version>3.9.0</version>
11         </dependency>
12         <dependency>
13             <groupId>io.zipkin.brave</groupId>
14             <artifactId>brave-web-servlet-filter</artifactId>
15             <version>3.9.0</version>
16         </dependency>

View Code

3.2、ZipkinConfig

 1 package com.xxx.service3.zipkin.brave.async;
 2
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5
 6 import com.github.kristofa.brave.Brave;
 7 import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler;
 8 import com.github.kristofa.brave.Sampler;
 9 import com.github.kristofa.brave.SpanCollector;
10 import com.github.kristofa.brave.http.DefaultSpanNameProvider;
11 import com.github.kristofa.brave.http.HttpSpanCollector;
12 import com.github.kristofa.brave.servlet.BraveServletFilter;
13
14 @Configuration
15 public class ZipkinConfig {
16     @Bean
17     public SpanCollector spanCollector() {
18         HttpSpanCollector.Config spanConfig = HttpSpanCollector.Config.builder()
19                                               .compressionEnabled(false)//默认false,span在transport之前是否会被gzipped。
20                                               .connectTimeout(5000)//5s,默认10s
21                                               .flushInterval(1)//1s
22                                               .readTimeout(6000)//5s,默认60s
23                                               .build();
24         return HttpSpanCollector.create("http://localhost:9411",
25                                         spanConfig,
26                                         new EmptySpanCollectorMetricsHandler());
27     }
28
29     @Bean
30     public Brave brave(SpanCollector spanCollector) {
31         Brave.Builder builder = new Brave.Builder("asyn3 - service3 - 3");//指定serviceName
32         builder.spanCollector(spanCollector);
33         builder.traceSampler(Sampler.create(1));//采集率
34         return builder.build();
35     }
36
37     @Bean
38     public BraveServletFilter braveServletFilter(Brave brave) {
39         /**
40          * 设置sr、ss拦截器
41          */
42         return new BraveServletFilter(brave.serverRequestInterceptor(),
43                                       brave.serverResponseInterceptor(),
44                                       new DefaultSpanNameProvider());
45     }
46 }

View Code

说明:指定了serviceName:"asyn3 - service3 - 3"

3.3、ZipkinAsyncController

 1 package com.xxx.service3.zipkin.brave.async;
 2
 3 import org.springframework.web.bind.annotation.RequestMapping;
 4 import org.springframework.web.bind.annotation.RequestMethod;
 5 import org.springframework.web.bind.annotation.RestController;
 6
 7 import io.swagger.annotations.Api;
 8 import io.swagger.annotations.ApiOperation;
 9
10 @Api("zipkin brave async api")
11 @RestController
12 @RequestMapping("/zipkin/async/service3")
13 public class ZipkinAsyncController {
14
15     @ApiOperation("trace第3步")
16     @RequestMapping(value = "/test3", method = RequestMethod.GET)
17     public String myboot3() {
18
19         try {
20             return "async - service3";
21         } catch (Exception e) {
22             e.printStackTrace();
23             return "";
24         }
25     }
26
27 }

View Code

4、service4

4.1、pom.xml

 1 <!-- zipkin brave -->
 2         <dependency>
 3             <groupId>io.zipkin.brave</groupId>
 4             <artifactId>brave-core</artifactId>
 5             <version>3.9.0</version>
 6         </dependency>
 7         <dependency>
 8             <groupId>io.zipkin.brave</groupId>
 9             <artifactId>brave-spancollector-http</artifactId>
10             <version>3.9.0</version>
11         </dependency>
12         <dependency>
13             <groupId>io.zipkin.brave</groupId>
14             <artifactId>brave-web-servlet-filter</artifactId>
15             <version>3.9.0</version>
16         </dependency>

View Code

4.2、ZipkinConfig

 1 package com.xxx.service4.zipkin.brave.async;
 2
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5
 6 import com.github.kristofa.brave.Brave;
 7 import com.github.kristofa.brave.EmptySpanCollectorMetricsHandler;
 8 import com.github.kristofa.brave.Sampler;
 9 import com.github.kristofa.brave.SpanCollector;
10 import com.github.kristofa.brave.http.DefaultSpanNameProvider;
11 import com.github.kristofa.brave.http.HttpSpanCollector;
12 import com.github.kristofa.brave.servlet.BraveServletFilter;
13
14 @Configuration
15 public class ZipkinConfig {
16     @Bean
17     public SpanCollector spanCollector() {
18         HttpSpanCollector.Config spanConfig = HttpSpanCollector.Config.builder()
19                                               .compressionEnabled(false)//默认false,span在transport之前是否会被gzipped。
20                                               .connectTimeout(5000)//5s,默认10s
21                                               .flushInterval(1)//1s
22                                               .readTimeout(6000)//5s,默认60s
23                                               .build();
24         return HttpSpanCollector.create("http://localhost:9411",
25                                         spanConfig,
26                                         new EmptySpanCollectorMetricsHandler());
27     }
28
29     @Bean
30     public Brave brave(SpanCollector spanCollector) {
31         Brave.Builder builder = new Brave.Builder("asyn4 - service4 - 4");//指定serviceName
32         builder.spanCollector(spanCollector);
33         builder.traceSampler(Sampler.create(1));//采集率
34         return builder.build();
35     }
36
37     @Bean
38     public BraveServletFilter braveServletFilter(Brave brave) {
39         /**
40          * 设置sr、ss拦截器
41          */
42         return new BraveServletFilter(brave.serverRequestInterceptor(),
43                                       brave.serverResponseInterceptor(),
44                                       new DefaultSpanNameProvider());
45     }
46
47 }

View Code

说明:指定了serviceName:"asyn4 - service4 - 4"

4.3、ZipkinAsyncController

 1 package com.xxx.service4.zipkin.brave.async;
 2
 3 import org.springframework.web.bind.annotation.RequestMapping;
 4 import org.springframework.web.bind.annotation.RequestMethod;
 5 import org.springframework.web.bind.annotation.RestController;
 6
 7 import io.swagger.annotations.Api;
 8 import io.swagger.annotations.ApiOperation;
 9
10 @Api("zipkin brave async api")
11 @RestController
12 @RequestMapping("/zipkin/async/service4")
13 public class ZipkinAsyncController {
14
15     @ApiOperation("trace第4步")
16     @RequestMapping(value = "/test4", method = RequestMethod.GET)
17     public String myboot3() {
18
19         try {
20             return "async - service4";
21         } catch (Exception e) {
22             e.printStackTrace();
23             return "";
24         }
25     }
26
27 }

View Code

二、测试结果

1、依赖关系图:

2、span时间消耗图

3、详情图

点击第4个span,查看详情:

转载于:https://www.cnblogs.com/java-zhao/p/5847459.html

第二十八章 springboot + zipkin(brave定制-AsyncHttpClient)相关推荐

  1. 第二十八章:化学学校

    第二十八章:化学学校 "后面的礼品,就算是之前的谢礼吧,如果以后还有类似的事情,只要你们做到,那么我崔门必将重谢!"崔门说道. "那到底该如何扼杀隐患呢?"李淳 ...

  2. 【正点原子MP157连载】第二十八章 A7和M4联合调试-摘自【正点原子】STM32MP1 M4裸机CubeIDE开发指南

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  3. 【正点原子FPGA连载】 第二十八章OV5640 DP显示实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

    1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670 3)全套实验源码+手册+视频下载地址: h ...

  4. 现实迷途 第二十八章 钱珊其人

    第二十八章 钱珊其人 注:原创作品,请尊重原作者,未经同意,请勿转载,否则追究责任. 面对江北的深情表白,钱珊沉默了一阵,然后说:"江北,谢谢你喜欢我,但是不好意思,我是个慢热型的人,我对你 ...

  5. 第二十八章 Caché 命令大全 TSTART 命令

    文章目录 第二十八章 Caché 命令大全 TSTART 命令 重点 大纲 参数 描述 嵌套事务 SQL Transactions 参数 pc 示例 第二十八章 Caché 命令大全 TSTART 命 ...

  6. 【正点原子MP157连载】第二十八章 Linux并发与竞争实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7

    1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...

  7. 【正点原子FPGA连载】 第二十八章 双路高速DA实验-摘自【正点原子】领航者ZYNQ之FPGA开发指南_V2.0

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  8. 疯狂的程序员-第二十八章

    一般情况下人在什么情况下喝酒?多半朋友聚会聊到兴奋了,或者发生了什么刺激人的大事,比如恋爱了,失恋了,发财了,破产了-- 绝影想这么晚了,又没有什么聚会,BOSS Liu找自己喝酒,肯定是受了什么刺激 ...

  9. 奋斗吧,程序员——第二十八章 叹年来踪迹,何事苦淹留

    二十五岁看十八岁时候朦胧的感情,自是感觉可笑.但如果三十岁回头看看二十五岁的感情依然可笑的话,那未免让人失望. 可二十五岁那年我的的确确是相信着爱这个字眼的. 我只是在漫长的岁月里等待一种表达. 既是 ...

最新文章

  1. 12,matlab中数据标记点选项参数,颜色 选项是参数,线性选项参数
  2. python syslog服务器_Python3+syslog使用及相关说明
  3. MyBatis 如何传递参数(全)
  4. mysql语句解析_mysql 语句的查询过程解析
  5. append替换代码后jquery不起作用_jQuery部分笔记
  6. 采访《以魂为中心的领导力》作者之问答
  7. c++ 数据结构之 线段树
  8. 45岁以后的IT人生
  9. 对应版本_DNF:韩服新增天域之母等13件特殊史诗,老版本装备全部直升100级
  10. Android读取手机通讯录
  11. java文件传输接口
  12. 引起1月12日WIN10 Flash停用原因
  13. VS中如何添加报表控件
  14. 中国月入过万的人多不多
  15. 如何使用repo管理本地私有仓库
  16. PPC修改注册表大全 (注册表必看)(转载)
  17. 如何使用STM32和BLE收集SHT85传感器数据?
  18. python---做一个恶搞程序
  19. 括号表示转孩子数组表示法
  20. 淘宝助理导出的csv文件使用的是什么编码,您猜?

热门文章

  1. my batis的理解
  2. Oracle数据库之事务
  3. 安卓自动化测试(一)
  4. 【转】Java类成员变量默认初始化规则
  5. 论 ACM 与泡妞 (转载)
  6. [导入]关于谭浩强[上]
  7. Java,想说爱你真不容易
  8. Maven与IDEA结合
  9. javaScript原型及继承
  10. codeforces——Little Pony and Expected Maximum