OSPP Add some RPC metrics for Spring-Cloud-Admin (#3836)
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-alibaba-examples</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>admin-message-common</artifactId>
|
||||
<name>Spring Cloud Starter Alibaba Admin Example Message Common</name>
|
||||
<description>Admin message exmaple common codes</description>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
</project>
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.examples.common;
|
||||
|
||||
/**
|
||||
* @author kwings6
|
||||
*/
|
||||
public class SimpleMsg {
|
||||
|
||||
private String msg;
|
||||
|
||||
public SimpleMsg() {
|
||||
}
|
||||
|
||||
public SimpleMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
server:
|
||||
port: 28087
|
||||
spring:
|
||||
application:
|
||||
name: rocketmq-sql-consume-example
|
||||
cloud:
|
||||
stream:
|
||||
function:
|
||||
definition: producer;consumer;
|
||||
rocketmq:
|
||||
binder:
|
||||
name-server: localhost:9876
|
||||
bindings:
|
||||
producer-out-0:
|
||||
producer:
|
||||
group: output_1
|
||||
consumer-in-0:
|
||||
consumer:
|
||||
# tag: {@code tag1||tag2||tag3 }; sql: {@code 'color'='blue' AND 'price'>100 } .
|
||||
subscription: sql:(color in ('red1', 'red2', 'red4') and price>3)
|
||||
bindings:
|
||||
producer-out-0:
|
||||
destination: sql
|
||||
consumer-in-0:
|
||||
destination: sql
|
||||
group: sql-group
|
||||
logging:
|
||||
level:
|
||||
org.springframework.context.support: debug
|
@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>spring-cloud-alibaba-examples</artifactId>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>admin-prometheus-consumer-example</artifactId>
|
||||
<name>Spring Cloud Admin Prometheus Consumer Example</name>
|
||||
<description>Example for Spring Cloud Alibaba Admin Consumer</description>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-openfeign</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-registry-prometheus</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--todo sentinel need to support GraalVM in future-->
|
||||
<!--<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
|
||||
</dependency>-->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>admin-message-common</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>${maven-deploy-plugin.version}</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.examples;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.alibaba.cloud.examples.common.SimpleMsg;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
|
||||
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
/**
|
||||
* @author kwings6
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableDiscoveryClient
|
||||
@EnableFeignClients
|
||||
@LoadBalancerClients({
|
||||
@LoadBalancerClient("service-provider")
|
||||
})
|
||||
public class ConsumerApplication {
|
||||
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(ConsumerApplication.class);
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ConsumerApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Consumer<Message<SimpleMsg>> consumer() {
|
||||
return msg -> {
|
||||
log.info(Thread.currentThread().getName() + " Consumer Receive New Messages: " + msg.getPayload().getMsg());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.examples;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.cloud.examples.common.SimpleMsg;
|
||||
import com.alibaba.cloud.examples.feign.EchoClient;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.rocketmq.common.message.MessageConst;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.cloud.client.discovery.DiscoveryClient;
|
||||
import org.springframework.cloud.client.discovery.ReactiveDiscoveryClient;
|
||||
import org.springframework.cloud.stream.function.StreamBridge;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* Example of remote invocation of service fusing and load balancing.
|
||||
*
|
||||
* @author kwings6
|
||||
*/
|
||||
|
||||
@RestController
|
||||
public class TestController {
|
||||
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(ConsumerApplication.class);
|
||||
|
||||
@Autowired
|
||||
private RestTemplate urlCleanedRestTemplate;
|
||||
|
||||
@Autowired
|
||||
private RestTemplate restTemplate;
|
||||
|
||||
@Autowired
|
||||
private EchoClient echoClient;
|
||||
|
||||
@Autowired
|
||||
private DiscoveryClient discoveryClient;
|
||||
|
||||
@Autowired
|
||||
private StreamBridge streamBridge;
|
||||
|
||||
private static final String SERVICE_PROVIDER_ADDRESS = "http://service-provider";
|
||||
|
||||
@Resource
|
||||
private ReactiveDiscoveryClient reactiveDiscoveryClient;
|
||||
|
||||
@Resource
|
||||
private WebClient.Builder webClientBuilder;
|
||||
|
||||
@GetMapping("/pro")
|
||||
public ApplicationRunner producerDelay() {
|
||||
return args -> {
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String key = "KEY" + i;
|
||||
Map<String, Object> headers = new HashMap<>();
|
||||
headers.put(MessageConst.PROPERTY_KEYS, key);
|
||||
headers.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);
|
||||
headers.put(MessageConst.PROPERTY_DELAY_TIME_LEVEL, 2);
|
||||
Message<SimpleMsg> msg = new GenericMessage(new SimpleMsg("Delay RocketMQ " + i), headers);
|
||||
streamBridge.send("producer-out-0", msg);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@GetMapping("/exp")
|
||||
public String exp() {
|
||||
return restTemplate.getForObject("https://httpbin.org/status/500", String.class);
|
||||
}
|
||||
|
||||
@GetMapping("/rt")
|
||||
public String rt() {
|
||||
return restTemplate.getForObject("https://httpbin.org/delay/3", String.class);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
public String get() {
|
||||
return restTemplate.getForObject("https://httpbin.org/get", String.class);
|
||||
}
|
||||
|
||||
@GetMapping("/all-services")
|
||||
public Flux<String> allServices() {
|
||||
return reactiveDiscoveryClient.getInstances("service-provider")
|
||||
.map(serviceInstance -> serviceInstance.getHost() + ":"
|
||||
+ serviceInstance.getPort());
|
||||
}
|
||||
|
||||
@GetMapping("/service-call/{name}")
|
||||
public Mono<String> serviceCall(@PathVariable("name") String name) {
|
||||
return webClientBuilder.build().get()
|
||||
.uri("http://service-provider/echo/" + name).retrieve()
|
||||
.bodyToMono(String.class);
|
||||
}
|
||||
|
||||
@GetMapping("/echo-rest/{str}")
|
||||
public String rest(@PathVariable String str) {
|
||||
return urlCleanedRestTemplate
|
||||
.getForObject(SERVICE_PROVIDER_ADDRESS + "/echo/" + str,
|
||||
String.class);
|
||||
}
|
||||
|
||||
@GetMapping("/index")
|
||||
public String index() {
|
||||
return restTemplate.getForObject(SERVICE_PROVIDER_ADDRESS, String.class);
|
||||
}
|
||||
|
||||
@GetMapping("/test")
|
||||
public String test() {
|
||||
return restTemplate
|
||||
.getForObject(SERVICE_PROVIDER_ADDRESS + "/test", String.class);
|
||||
}
|
||||
|
||||
@GetMapping("/sleep")
|
||||
public String sleep() {
|
||||
return restTemplate
|
||||
.getForObject(SERVICE_PROVIDER_ADDRESS + "/sleep", String.class);
|
||||
}
|
||||
|
||||
@GetMapping("/notFound-feign")
|
||||
public String notFound() {
|
||||
return echoClient.notFound();
|
||||
}
|
||||
|
||||
@GetMapping("/divide-feign")
|
||||
public String divide(@RequestParam Integer a, @RequestParam Integer b) {
|
||||
return echoClient.divide(a, b);
|
||||
}
|
||||
|
||||
@GetMapping("/divide-feign2")
|
||||
public String divide(@RequestParam Integer a) {
|
||||
return echoClient.divide(a);
|
||||
}
|
||||
|
||||
@GetMapping("/echo-feign/{str}")
|
||||
public String feign(@PathVariable String str) {
|
||||
return echoClient.echo(str);
|
||||
}
|
||||
|
||||
@GetMapping("/services/{service}")
|
||||
public Object client(@PathVariable String service) {
|
||||
return discoveryClient.getInstances(service);
|
||||
}
|
||||
|
||||
@GetMapping("/services")
|
||||
public Object services() {
|
||||
return discoveryClient.getServices();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.examples.configuration;
|
||||
|
||||
import com.alibaba.cloud.examples.feign.EchoClient;
|
||||
import com.alibaba.cloud.examples.feign.EchoClientFallback;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
/**
|
||||
* Configuration for Feign.
|
||||
*
|
||||
* @author kwings6
|
||||
*/
|
||||
public class FeignConfiguration {
|
||||
|
||||
@Bean
|
||||
public EchoClient echoClientFallback() {
|
||||
return new EchoClientFallback();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.examples.configuration;
|
||||
|
||||
import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
|
||||
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Load balancing and sentinel configuration for RestTemplate.
|
||||
*
|
||||
* @author kwings6
|
||||
*/
|
||||
@Configuration
|
||||
public class RestTemplateConfiguration {
|
||||
|
||||
@LoadBalanced
|
||||
@Bean
|
||||
// todo sentinel need to support GraalVM in future
|
||||
// @SentinelRestTemplate(urlCleanerClass = UrlCleaner.class, urlCleaner = "clean")
|
||||
public RestTemplate urlCleanedRestTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
|
||||
@LoadBalanced
|
||||
@Bean
|
||||
// todo sentinel need to support GraalVM in future
|
||||
@SentinelRestTemplate
|
||||
public RestTemplate restTemplate() {
|
||||
return new RestTemplate();
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.examples.configuration;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Change the request path containing echo.
|
||||
*
|
||||
* @author kwings6
|
||||
*/
|
||||
public class UrlCleaner {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(UrlCleaner.class);
|
||||
|
||||
private static final String URL_CLEAN_ECHO = ".*/echo/.*";
|
||||
|
||||
public static String clean(String url) {
|
||||
LOGGER.info("enter urlCleaner");
|
||||
if (url.matches(URL_CLEAN_ECHO)) {
|
||||
LOGGER.info("change url");
|
||||
url = url.replaceAll("/echo/.*", "/echo/{str}");
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.examples.configuration;
|
||||
|
||||
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
/**
|
||||
* Configuration for web client.
|
||||
*
|
||||
* @author kwings6
|
||||
*/
|
||||
|
||||
@Configuration
|
||||
public class WebClientConfiguration {
|
||||
|
||||
@Bean
|
||||
@LoadBalanced
|
||||
public WebClient.Builder webClient() {
|
||||
return WebClient.builder();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.examples.feign;
|
||||
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
/**
|
||||
* Provide the external exposure interface of the service calling client.
|
||||
*
|
||||
* @author kwings6
|
||||
*/
|
||||
@FeignClient(name = "service-provider", contextId = "service-provider")
|
||||
public interface EchoClient {
|
||||
|
||||
/**
|
||||
* Call the echo method of the remote provider or roll back when the service is blown.
|
||||
*
|
||||
* @param str str
|
||||
* @return {@link String}
|
||||
*/
|
||||
@GetMapping("/echo/{str}")
|
||||
String echo(@PathVariable("str") String str);
|
||||
|
||||
/**
|
||||
* Call the divide method of the remote provider or roll back when the service is blown.
|
||||
*
|
||||
* @param a a
|
||||
* @param b b
|
||||
* @return {@link String}
|
||||
*/
|
||||
@GetMapping("/divide")
|
||||
String divide(@RequestParam("a") Integer a, @RequestParam("b") Integer b);
|
||||
|
||||
/**
|
||||
* Test that the default method calls the remote method is still a remote call.
|
||||
*
|
||||
* @param a a
|
||||
* @return {@link String}
|
||||
*/
|
||||
default String divide(Integer a) {
|
||||
return divide(a, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the notFound method of the remote provider or roll back when the service is blown.
|
||||
*
|
||||
* @return {@link String}
|
||||
*/
|
||||
@GetMapping("/notFound")
|
||||
String notFound();
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.examples.feign;
|
||||
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
/**
|
||||
* When the service is blown, the fallback operation is performed.
|
||||
*
|
||||
* @author kwings6
|
||||
*/
|
||||
public class EchoClientFallback implements EchoClient {
|
||||
|
||||
@Override
|
||||
public String echo(@PathVariable("str") String str) {
|
||||
return "echo fallback";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String divide(@RequestParam Integer a, @RequestParam Integer b) {
|
||||
return "divide fallback";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String notFound() {
|
||||
return "notFound fallback";
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
management:
|
||||
endpoint:
|
||||
prometheus:
|
||||
enabled: true
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: '*'
|
||||
prometheus:
|
||||
metrics:
|
||||
export:
|
||||
enabled: true
|
||||
server:
|
||||
port: 18083
|
||||
spring:
|
||||
application:
|
||||
name: service-consumer
|
||||
cloud:
|
||||
loadbalancer:
|
||||
nacos:
|
||||
enabled: true
|
||||
ribbon:
|
||||
enabled: false
|
||||
nacos:
|
||||
discovery:
|
||||
fail-fast: true
|
||||
server-addr: 127.0.0.1:8848
|
||||
password: nacos
|
||||
username: nacos
|
||||
refresh:
|
||||
enabled: false
|
||||
sentinel:
|
||||
transport:
|
||||
dashboard: localhost:8080
|
||||
eager: true
|
||||
stream:
|
||||
function:
|
||||
definition: consumer;
|
||||
rocketmq:
|
||||
binder:
|
||||
name-server: localhost:9876
|
||||
bindings:
|
||||
consumer-in-0:
|
||||
consumer:
|
||||
messageModel: BROADCASTING
|
||||
bindings:
|
||||
consumer-in-0:
|
||||
destination: broadcast
|
||||
group: broadcast-consumer
|
@ -0,0 +1,78 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>spring-cloud-alibaba-examples</artifactId>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>admin-prometheus-provider-example</artifactId>
|
||||
<name>Spring Cloud Admin Prometheus Provider Example</name>
|
||||
<description>Example for Spring Cloud Alibaba Admin Provider</description>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>17</maven.compiler.source>
|
||||
<maven.compiler.target>17</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-stream-rocketmq</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>admin-message-common</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.micrometer</groupId>
|
||||
<artifactId>micrometer-registry-prometheus</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<version>${maven-deploy-plugin.version}</version>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.examples;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
|
||||
import jakarta.annotation.Resource;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Provide interfaces to consumers.
|
||||
*
|
||||
* @author kwings6
|
||||
*/
|
||||
|
||||
@RestController
|
||||
public class EchoController {
|
||||
|
||||
@Resource
|
||||
private NacosDiscoveryProperties nacosDiscoveryProperties;
|
||||
|
||||
@GetMapping("/sayHello")
|
||||
public String sayHello() {
|
||||
System.out.println("beifangwen");
|
||||
return "nihao";
|
||||
}
|
||||
|
||||
@GetMapping("/")
|
||||
public ResponseEntity<String> index() {
|
||||
return new ResponseEntity<>("index error", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
@GetMapping("/test")
|
||||
public ResponseEntity<String> test() {
|
||||
return new ResponseEntity<>("error", HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
@GetMapping("/sleep")
|
||||
public String sleep() {
|
||||
try {
|
||||
Thread.sleep(1000L);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "ok";
|
||||
}
|
||||
|
||||
@GetMapping("/echo/{string}")
|
||||
public String echo(@PathVariable String string) {
|
||||
return "hello Nacos Discovery " + string;
|
||||
}
|
||||
|
||||
@GetMapping("/divide")
|
||||
public String divide(@RequestParam Integer a, @RequestParam Integer b) {
|
||||
if (b == 0) {
|
||||
return String.valueOf(0);
|
||||
}
|
||||
else {
|
||||
return String.valueOf(a / b);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/zone")
|
||||
public String zone() {
|
||||
Map<String, String> metadata = nacosDiscoveryProperties.getMetadata();
|
||||
return "provider zone " + metadata.get("zone");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.examples;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.cloud.examples.common.SimpleMsg;
|
||||
import org.apache.rocketmq.common.message.MessageConst;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.ApplicationRunner;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.stream.function.StreamBridge;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.support.GenericMessage;
|
||||
|
||||
/**
|
||||
* @author kwings6
|
||||
*/
|
||||
|
||||
@EnableDiscoveryClient
|
||||
@SpringBootApplication
|
||||
public class ProviderApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ProviderApplication.class, args);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private StreamBridge streamBridge;
|
||||
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(ProviderApplication.class);
|
||||
|
||||
@Bean
|
||||
public ApplicationRunner producer() {
|
||||
return args -> {
|
||||
Thread.sleep(30000);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String key = "KEY" + i;
|
||||
Map<String, Object> headers = new HashMap<>();
|
||||
headers.put(MessageConst.PROPERTY_KEYS, key);
|
||||
headers.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);
|
||||
Message<SimpleMsg> msg = new GenericMessage<SimpleMsg>(new SimpleMsg("Hello RocketMQ " + i), headers);
|
||||
streamBridge.send("producer-out-0", msg);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
management:
|
||||
endpoint:
|
||||
health:
|
||||
show-details: always
|
||||
endpoints:
|
||||
web:
|
||||
exposure:
|
||||
include: '*'
|
||||
server:
|
||||
port: 18080
|
||||
spring:
|
||||
application:
|
||||
name: service-provider
|
||||
cloud:
|
||||
nacos:
|
||||
discovery:
|
||||
enabled: true
|
||||
server-addr: 127.0.0.1:8848
|
||||
password: nacos
|
||||
username: nacos
|
||||
stream:
|
||||
rocketmq:
|
||||
binder:
|
||||
name-server: localhost:9876
|
||||
bindings:
|
||||
producer-out-0:
|
||||
producer:
|
||||
group: output_1
|
||||
bindings:
|
||||
producer-out-0:
|
||||
destination: broadcast
|
@ -0,0 +1,49 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana
|
||||
hostname: "otel-grafana"
|
||||
container_name: "otel-grafana"
|
||||
ports:
|
||||
- "3000:3000"
|
||||
|
||||
# Jaeger
|
||||
# jaeger-all-in-one:
|
||||
# image: jaegertracing/all-in-one:latest
|
||||
# ports:
|
||||
# - "16686:16686"
|
||||
# - "14268"
|
||||
# - "14250:14250"
|
||||
# environment:
|
||||
# - COLLECTOR_OTLP_ENABLED=true
|
||||
|
||||
# Zipkin
|
||||
zipkin-all-in-one:
|
||||
image: openzipkin/zipkin:latest
|
||||
hostname: zipkin
|
||||
ports:
|
||||
- "9411:9411"
|
||||
|
||||
otel-collector:
|
||||
container_name: "otel-collector"
|
||||
hostname: "otel-collector"
|
||||
image: otel/opentelemetry-collector
|
||||
volumes:
|
||||
- ./otel/config.yml:/etc/otel/config.yml
|
||||
ports:
|
||||
# - 18880:1888 # pprof extension
|
||||
# - 8888:8888 # Prometheus metrics exposed by the Collector
|
||||
- "8889:8889" # Prometheus exporter metrics
|
||||
# - 13133:13133 # health_check extension
|
||||
- "4317:4317" # OTLP gRPC receiver
|
||||
- "4318:4318" # OTLP http receiver
|
||||
# - 55679:55679 # zpages extensio
|
||||
|
||||
prometheus:
|
||||
container_name: prometheus
|
||||
image: prom/prometheus:latest
|
||||
volumes:
|
||||
- ./prometheus/config.yml:/etc/prometheus/prometheus.yml
|
||||
ports:
|
||||
- "9090:9090"
|
@ -0,0 +1,42 @@
|
||||
# https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/main/examples/demo/otel-collector-config.yaml
|
||||
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
grpc:
|
||||
endpoint: "0.0.0.0:4317"
|
||||
http:
|
||||
endpoint: "0.0.0.0:4318"
|
||||
|
||||
processors:
|
||||
batch:
|
||||
|
||||
exporters:
|
||||
prometheus:
|
||||
endpoint: "0.0.0.0:8889"
|
||||
namespace: promexample
|
||||
const_labels:
|
||||
label1: value1
|
||||
logging:
|
||||
loglevel: debug
|
||||
|
||||
zipkin:
|
||||
endpoint: "http://zipkin:9411/api/v2/spans"
|
||||
format: proto
|
||||
|
||||
# otlp/jaeger:
|
||||
# endpoint: jaeger-all-in-one:14250
|
||||
# tls:
|
||||
# insecure: true
|
||||
|
||||
service:
|
||||
# extensions: [health_check]
|
||||
pipelines:
|
||||
traces:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [logging, zipkin]
|
||||
metrics:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [logging, prometheus]
|
@ -0,0 +1,20 @@
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
|
||||
- job_name: 'prometheus'
|
||||
static_configs:
|
||||
- targets: ['127.0.0.1:9090']
|
||||
|
||||
- job_name: 'admin-prometheus'
|
||||
metrics_path: '/actuator/prometheus'
|
||||
static_configs:
|
||||
- targets: [ '127.0.0.1:18083' ]
|
||||
|
||||
#
|
||||
# - job_name: 'otel-collector'
|
||||
# scrape_interval: 2s
|
||||
# static_configs:
|
||||
# - targets: ['otel-collector:8888']
|
After Width: | Height: | Size: 93 KiB |
After Width: | Height: | Size: 147 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 563 KiB |
After Width: | Height: | Size: 92 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 88 KiB |
After Width: | Height: | Size: 86 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 60 KiB |
After Width: | Height: | Size: 5.0 KiB |
After Width: | Height: | Size: 4.1 KiB |
@ -0,0 +1,321 @@
|
||||
# Spring Cloud Alibaba Admin Example
|
||||
|
||||
## Project description
|
||||
|
||||
This project demonstrates how to use Spring Cloud Alibaba Admin related Starter to obtain monitoring data for Spring Cloud Alibaba instances. And displayed on Prometheus and Grafana.
|
||||
|
||||
The data in Admin comes from the native embedding points in Starter using MicroMeter.
|
||||
|
||||
This project only includes Nacos, RocketMQ, Sentinel indicators. If you want to view Seata related indicators, you can start Seata Example and follow the steps below to view them.
|
||||
|
||||
## Nacos Server 2.4.2 is properly configured and started
|
||||
|
||||
In Nacos 2.4.2, functions related to user authentication are added. When starting Nacos Server for the first time, it needs to be configured correctly to avoid the problem of startup failure.
|
||||
|
||||
### Download Nacos Server
|
||||
|
||||
> The Nacos serv version used in this example is 2.2.3!
|
||||
|
||||
Nacos supports both direct download and source code construction. **Nacos Server version 2.2.3 is recommended for Spring Cloud Alibaba 2022.x.**
|
||||
|
||||
1. Direct download: [Nacos Server download page](https://github.com/alibaba/nacos/releases)
|
||||
2. Source code construction: Enter Nacos [Github project page](https://github.com/alibaba/nacos), git clone the code to the local compilation and packaging [参考文档](https://nacos.io/zh-cn/docs/quick-start.html).
|
||||
|
||||
### Configure the Nacos Server
|
||||
|
||||
Open the `\nacos-server-2.2.3\conf\application.properties` configuration file and modify the following configuration items:
|
||||
|
||||
#### Configure the data source
|
||||
|
||||
Take the MySQL database as an example here, and use the `nacos-server-2.2.3\conf\mysql-schema.sql` initialization database table file. Modify the following configuration as well
|
||||
|
||||
```properties
|
||||
#*************** Config Module Related Configurations ***************#
|
||||
### If use MySQL as datasource:
|
||||
spring.datasource.platform=mysql
|
||||
|
||||
### Count of DB:
|
||||
db.num=1
|
||||
|
||||
### Connect URL of DB:
|
||||
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
|
||||
db.user.0=root
|
||||
db.password.0=root
|
||||
|
||||
### Connection pool configuration: hikariCP
|
||||
db.pool.config.connectionTimeout=30000
|
||||
db.pool.config.validationTimeout=10000
|
||||
db.pool.config.maximumPoolSize=20
|
||||
db.pool.config.minimumIdle=2
|
||||
```
|
||||
|
||||
#### Turn on authentication
|
||||
|
||||
**Note: If it is not enabled, login failure exception will occur in 2.4.2!**
|
||||
|
||||
```properties
|
||||
### The auth system to use, currently only 'nacos' and 'ldap' is supported:
|
||||
nacos.core.auth.system.type=nacos
|
||||
|
||||
### If turn on auth system:
|
||||
nacos.core.auth.enabled=true
|
||||
```
|
||||
|
||||
#### Set the server authentication key
|
||||
|
||||
```properties
|
||||
nacos.core.auth.server.identity.key=test
|
||||
nacos.core.auth.server.identity.value=test
|
||||
```
|
||||
|
||||
#### Set the default token
|
||||
|
||||
```properties
|
||||
### The default token (Base64 String):
|
||||
nacos.core.auth.plugin.nacos.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
|
||||
```
|
||||
|
||||
** When using the Nacos service discovery and configuration function, be sure to configure `username` and `password` attribute, otherwise the user will not be found! **
|
||||
|
||||
#### Open API authentication
|
||||
|
||||
Authentication is required when using the Open api interface in nacos server 2.4.2: For more details, please refer to: [Nacos api authentication](https://nacos.io/zh-cn/docs/auth.html)
|
||||
|
||||
1. Obtain accessToken: Use username and password to log in to the nacos server:
|
||||
|
||||
`curl -X POST '127.0.0.1:8848/nacos/v1/auth/login' -d 'username=nacos&password=nacos'`
|
||||
|
||||
If the username and password are correct, the returned information is as follows:
|
||||
|
||||
`{"accessToken":"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyOTE2Nn0.2TogGhhr11_vLEjqKko1HJHUJEmsPuCxkur-CfNojDo", "tokenTtl": 18000, "globalAdmin": true}`
|
||||
|
||||
2. Use accessToken to request the nacos api interface:
|
||||
|
||||
`curl -X GET '127.0.0.1:8848/nacos/v1/cs/configs?accessToken=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJuYWNvcyIsImV4cCI6MTYwNTYyMzkyM30.O-s2yWfDSUZ7Svd3Vs7jy9tsfDNHs1SuebJB4KlNY8Q&dataId=nacos.example.1&group=nacos_group'`
|
||||
|
||||
### Start the Nacos Server
|
||||
|
||||
1. Start Nacos Server, enter the folder after downloading to the local and decompressing (enter the folder after compiling and packaging by using the source code construction method), then enter its relative folder `nacos/bin`, and execute the following command according to the actual situation of the operating system. [详情参考此文档](https://nacos.io/zh-cn/docs/quick-start.html)。
|
||||
|
||||
1. Linux/Unix/Mac operating system, execute the command
|
||||
|
||||
`sh startup.sh -m standalone`
|
||||
|
||||
2. Windows operating system, executing command
|
||||
|
||||
`cmd startup.cmd`
|
||||
|
||||
2. Access Nacos Server Console.
|
||||
|
||||
The browser enters the address http://127.0.0.1:8848/nacos , **The first login needs to bind the nacos user, because the new version adds authentication, and the user name and password need to be configured during application registration and configuration binding.**
|
||||
|
||||
## Configure RocketMQ and start it
|
||||
|
||||
### Spring Cloud Alibaba RocketMQ
|
||||
|
||||
**Firstly, it is necessary to start the Name Server and Broker of RocketMQ**
|
||||
|
||||
### Download and Startup RocketMQ
|
||||
|
||||
You should startup Name Server and Broker before using RocketMQ Binder.
|
||||
|
||||
1. Download [RocketMQ](https://archive.apache.org/dist/rocketmq/4.3.2/rocketmq-all-4.3.2-bin-release.zip) and unzip it.
|
||||
2. Startup Name Server
|
||||
|
||||
```
|
||||
sh bin/mqnamesrv
|
||||
```
|
||||
|
||||
3. Startup Broker
|
||||
|
||||
```
|
||||
sh bin/mqbroker -n localhost:9876
|
||||
```
|
||||
|
||||
## Admin application example
|
||||
|
||||
#### After completing the configuration of the front-end components, start admin-prometheus-consumer-example和admin-prometheus-provider-example in order
|
||||
|
||||
```java
|
||||
@SpringBootApplication
|
||||
@EnableDiscoveryClient
|
||||
@EnableFeignClients
|
||||
@LoadBalancerClients({
|
||||
@LoadBalancerClient("service-provider")
|
||||
})
|
||||
public class ConsumerApplication {
|
||||
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(ConsumerApplication.class);
|
||||
|
||||
@Autowired
|
||||
private StreamBridge streamBridge;
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ConsumerApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Consumer<Message<SimpleMsg>> consumer() {
|
||||
return msg -> {
|
||||
log.info(Thread.currentThread().getName() + " Consumer Receive New Messages: " + msg.getPayload().getMsg());
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```java
|
||||
@EnableDiscoveryClient
|
||||
@SpringBootApplication
|
||||
public class ProviderApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ProviderApplication.class, args);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private StreamBridge streamBridge;
|
||||
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(ProviderApplication.class);
|
||||
|
||||
@Bean
|
||||
public ApplicationRunner producer() {
|
||||
return args -> {
|
||||
Thread.sleep(30000);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
String key = "KEY" + i;
|
||||
Map<String, Object> headers = new HashMap<>();
|
||||
headers.put(MessageConst.PROPERTY_KEYS, key);
|
||||
headers.put(MessageConst.PROPERTY_ORIGIN_MESSAGE_ID, i);
|
||||
Message<SimpleMsg> msg = new GenericMessage<SimpleMsg>(new SimpleMsg("Hello RocketMQ " + i), headers);
|
||||
streamBridge.send("producer-out-0", msg);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Use Nacos RestTemplate, OpenFeign, Reactive respectively
|
||||
|
||||
1. Address bar input
|
||||
|
||||
`http://localhost:18083/echo-rest/test`
|
||||
|
||||
`http://localhost:18083/echo-feign/test`
|
||||
|
||||
`http://localhost:18083/service-call/test`
|
||||
|
||||
2. Input` http://localhost:18083/actuator/metrics `view metrics
|
||||
|
||||
```text
|
||||
"spring.cloud.rpc.openfeign.qps"
|
||||
"spring.cloud.rpc.reactive.qps"
|
||||
"spring.cloud.rpc.restTemplate.qps"
|
||||
```
|
||||
|
||||
3. Input` http://localhost:18083/actuator/metrics/spring -Cloud.rpc.reactive. qps ` can view detailed data
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "spring-cloud.rpc.reactive.qps",
|
||||
"description": "Spring Cloud Alibaba QPS metrics when use Reactive RPC Call.",
|
||||
"baseUnit": "SECONDS",
|
||||
"measurements": [{
|
||||
"statistic": "COUNT",
|
||||
"value": 17
|
||||
}],
|
||||
"availableTags": [{
|
||||
"tag": "sca.reactive.rpc.method",
|
||||
"values": ["GET"]
|
||||
},
|
||||
{
|
||||
"tag": "sca.reactive.rpc",
|
||||
"values": ["url: http://10.2.64.89:18080/echo/11 method: GET status: 200 OK"]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
#### Using Sentinel RestTemplate for Grading and Flow
|
||||
|
||||
1. Enter in the address bar
|
||||
`http://localhost:18083/rt`
|
||||
|
||||
`http://localhost:18083/get`
|
||||
|
||||
2. Input`http://localhost:18083/actuator/metrics`View metrics
|
||||
|
||||
```text
|
||||
"spring.cloud.alibaba.sentinel.degrade.sum"
|
||||
"spring.cloud.alibaba.sentinel.flow.sum"
|
||||
```
|
||||
|
||||
3. input`http://localhost:18083/actuator/metrics/spring.cloud.alibaba.sentinel.degrade.sum`can view detailed data
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "spring.cloud.alibaba.sentinel.degrade.sum",
|
||||
"measurements": [{
|
||||
"statistic": "COUNT",
|
||||
"value": 16
|
||||
}],
|
||||
"availableTags": []
|
||||
}
|
||||
```
|
||||
|
||||
## Integrate Prometheus and Grafana
|
||||
|
||||
#### First provide the address` http://localhost:18083/actuator/prometheus `View data transmitted to Prometheus
|
||||
|
||||
<img src="./images/image-20241025103000343.png" alt="image-20241025103000343.png" style="zoom: 50%;" />
|
||||
|
||||
**Start Prometheus and Grafana through Docker. Before starting, modify the IP address of the targets location in the config. yml folder of Prometheus to the IP address of your personal computer**
|
||||
|
||||
```yaml
|
||||
- job_name: 'admin-prometheus'
|
||||
metrics_path: '/actuator/prometheus'
|
||||
static_configs:
|
||||
- targets: [ '127.0.0.1:18083' ]
|
||||
```
|
||||
|
||||
**Input` http://localhost:9090/targets?search= `There are two addresses for scraping metrics**
|
||||
|
||||
<img src="./images/image-20241025103641209.png" alt="image-20241025103641209.png" style="zoom: 50%;" />
|
||||
|
||||
<img src="./images/image-20241025103649642.png" alt="image-20241025103649642.png" style="zoom: 50%;" />
|
||||
|
||||
**Then search in the search box to see the metrics**
|
||||
|
||||
<img src="./images/image-20241024225418675.png" alt="image-20241024225418675.png" style="zoom: 50%;" />
|
||||
|
||||
<img src="./images/image-20241024225435691.png" alt="image-20241024225435691.png" style="zoom: 50%;" />
|
||||
|
||||
#### Starting Grafana with Docker
|
||||
|
||||
**Enter admin for both account and password, then click on 'skip'**
|
||||
|
||||
<img src="./images/image-20241024225527267.png" alt="image-20241024225527267.png" style="zoom: 50%;" />
|
||||
|
||||
**Add data source**
|
||||
|
||||
<img src="./images/image-20241024225604518.png" alt="image-20241024225604518.png" style="zoom: 50%;" />
|
||||
|
||||
**Enter personal computer IP+9090 here**
|
||||
|
||||
<img src="./images/image-20241024225633698.png" alt="image-20241024225633698.png" style="zoom: 50%;" />
|
||||
|
||||
**Is the test successful**
|
||||
|
||||
<img src="./images/image-20241024225708457.png" alt="image-20241024225708457.png" style="zoom: 50%;" />
|
||||
|
||||
**Return to dashboard and import the JSON file from the import folder as the Grafana panel**
|
||||
|
||||
[This panel is modified based on the SLS JVM monitoring dashboard](https://grafana.com/grafana/dashboards/12856-jvm-micrometer/)
|
||||
|
||||
<img src="./images/image-20241024225744092.png" alt="image-20241024225744092.png" style="zoom: 50%;" />
|
||||
|
||||
<img src="./images/image-20241024225835039.png" alt="image-20241024225835039.png" style="zoom: 50%;" />
|
||||
|
||||
<img src="./images/image-20241025001135834.png" alt="image-20241025001135834.png" style="zoom: 50%;" />
|
||||
|
||||
<img src="./images/image-20241025001146055.png" alt="image-20241025001146055.png" style="zoom: 50%;" />
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.metrics;
|
||||
|
||||
import com.alibaba.cloud.nacos.ConditionalOnNacosDiscoveryEnabled;
|
||||
import com.alibaba.cloud.nacos.metrics.aop.NacosDiscoveryMetricsReactiveBeanPostProcessor;
|
||||
import com.alibaba.cloud.nacos.metrics.aop.NacosDiscoveryMetricsRestBeanPostProcessor;
|
||||
import com.alibaba.cloud.nacos.metrics.aop.interceptor.NacosDiscoveryMetricsOpenFeignInterceptor;
|
||||
import com.alibaba.cloud.nacos.metrics.aop.interceptor.NacosDiscoveryMetricsReactiveInterceptor;
|
||||
import com.alibaba.cloud.nacos.metrics.aop.interceptor.NacosDiscoveryMetricsRestTemplateInterceptor;
|
||||
import feign.Client;
|
||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.cloud.client.ConditionalOnDiscoveryEnabled;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnDiscoveryEnabled
|
||||
@ConditionalOnNacosDiscoveryEnabled
|
||||
public class NacosMetricsAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, PrometheusMeterRegistry registry) {
|
||||
return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, "");
|
||||
}
|
||||
|
||||
@ConditionalOnClass(WebClient.class)
|
||||
@ConditionalOnBean(WebClient.Builder.class)
|
||||
protected static class NacosMetricsReactiveConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public NacosDiscoveryMetricsReactiveInterceptor nacosDiscoveryMetricsReactiveInterceptor() {
|
||||
return new NacosDiscoveryMetricsReactiveInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NacosDiscoveryMetricsReactiveBeanPostProcessor nacosDiscoveryMetricsReactiveBeanPostProcessor() {
|
||||
return new NacosDiscoveryMetricsReactiveBeanPostProcessor();
|
||||
}
|
||||
}
|
||||
|
||||
@ConditionalOnClass(RestTemplate.class)
|
||||
protected static class NacosMetricsRestConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public NacosDiscoveryMetricsRestTemplateInterceptor nacosDiscoveryMetricsRestTemplateInterceptor() {
|
||||
return new NacosDiscoveryMetricsRestTemplateInterceptor();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public NacosDiscoveryMetricsRestBeanPostProcessor nacosDiscoveryMetricsRestBeanPostProcessor() {
|
||||
return new NacosDiscoveryMetricsRestBeanPostProcessor();
|
||||
}
|
||||
}
|
||||
|
||||
@ConditionalOnClass(Client.class)
|
||||
protected static class NacosMetricsOpenFeignConfiguration {
|
||||
|
||||
@Bean(name = "nacosDiscoveryMetricsOpenFeignInterceptor")
|
||||
@ConditionalOnMissingBean
|
||||
public NacosDiscoveryMetricsOpenFeignInterceptor nacosDiscoveryMetricsOpenFeignInterceptor() {
|
||||
return new NacosDiscoveryMetricsOpenFeignInterceptor();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.metrics.aop;
|
||||
|
||||
import com.alibaba.cloud.nacos.metrics.aop.interceptor.NacosDiscoveryMetricsReactiveInterceptor;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.web.reactive.function.client.WebClient;
|
||||
|
||||
public class NacosDiscoveryMetricsReactiveBeanPostProcessor implements BeanPostProcessor {
|
||||
@Autowired
|
||||
private NacosDiscoveryMetricsReactiveInterceptor reactiveInterceptor;
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof WebClient.Builder) {
|
||||
WebClient.Builder builder = (WebClient.Builder) bean;
|
||||
builder.filter(reactiveInterceptor);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.metrics.aop;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.alibaba.cloud.nacos.metrics.aop.interceptor.NacosDiscoveryMetricsRestTemplateInterceptor;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
|
||||
public class NacosDiscoveryMetricsRestBeanPostProcessor implements BeanPostProcessor {
|
||||
@Autowired
|
||||
private NacosDiscoveryMetricsRestTemplateInterceptor restTemplateInterceptor;
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof RestTemplate) {
|
||||
RestTemplate restTemplate = (RestTemplate) bean;
|
||||
restTemplate.setInterceptors(Arrays.asList(restTemplateInterceptor));
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.metrics.aop.interceptor;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import feign.InvocationContext;
|
||||
import feign.RequestInterceptor;
|
||||
import feign.RequestTemplate;
|
||||
import feign.Response;
|
||||
import feign.ResponseInterceptor;
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
|
||||
public class NacosDiscoveryMetricsOpenFeignInterceptor implements ResponseInterceptor, RequestInterceptor {
|
||||
|
||||
@Autowired
|
||||
private PrometheusMeterRegistry prometheusMeterRegistry;
|
||||
RequestTemplate request;
|
||||
|
||||
@Override
|
||||
public Object intercept(InvocationContext invocationContext, Chain chain) throws Exception {
|
||||
|
||||
Response response = invocationContext.response();
|
||||
|
||||
Counter qpsCounter = Counter.builder("spring.cloud.rpc.openfeign.qps")
|
||||
.description("Spring Cloud Alibaba QPS metrics when use OpenFeign RPC Call.")
|
||||
.baseUnit(TimeUnit.SECONDS.name())
|
||||
.tag("sca.openfeign.rpc", "url: " + request.url()
|
||||
+ " method: " + request.method()
|
||||
+ " status: " + response.status())
|
||||
.register(prometheusMeterRegistry);
|
||||
|
||||
qpsCounter.increment();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResponseInterceptor andThen(ResponseInterceptor nextInterceptor) {
|
||||
return ResponseInterceptor.super.andThen(nextInterceptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chain apply(Chain chain) {
|
||||
return ResponseInterceptor.super.apply(chain);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(RequestTemplate requestTemplate) {
|
||||
this.request = requestTemplate;
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.metrics.aop.interceptor;
|
||||
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.web.reactive.function.client.ClientRequest;
|
||||
import org.springframework.web.reactive.function.client.ClientResponse;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
|
||||
import org.springframework.web.reactive.function.client.ExchangeFunction;
|
||||
|
||||
|
||||
public class NacosDiscoveryMetricsReactiveInterceptor implements ExchangeFilterFunction {
|
||||
|
||||
@Autowired
|
||||
private PrometheusMeterRegistry prometheusMeterRegistry;
|
||||
|
||||
@Override
|
||||
public Mono<ClientResponse> filter(ClientRequest request, ExchangeFunction next) {
|
||||
|
||||
HttpMethod method = request.method();
|
||||
URI url = request.url();
|
||||
|
||||
return next.exchange(request).doOnSuccess(response -> {
|
||||
Counter qpsCounter = Counter.builder("spring.cloud.rpc.reactive.qps")
|
||||
.description("Spring Cloud Alibaba QPS metrics when use Reactive RPC Call.")
|
||||
.baseUnit(TimeUnit.SECONDS.name()).tag("sca.reactive.rpc.method", method.name())
|
||||
.tag("sca.reactive.rpc", "url: " + url + " method: " + method.name() + " status: " + response.statusCode())
|
||||
.register(prometheusMeterRegistry);
|
||||
|
||||
qpsCounter.increment();
|
||||
|
||||
response.bodyToMono(String.class).doOnNext(System.out::println).subscribe();
|
||||
}).doOnError(error -> {
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExchangeFilterFunction andThen(ExchangeFilterFunction afterFilter) {
|
||||
return ExchangeFilterFunction.super.andThen(afterFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExchangeFunction apply(ExchangeFunction exchange) {
|
||||
return ExchangeFilterFunction.super.apply(exchange);
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.nacos.metrics.aop.interceptor;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.http.client.ClientHttpRequestExecution;
|
||||
import org.springframework.http.client.ClientHttpRequestInterceptor;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
|
||||
|
||||
public class NacosDiscoveryMetricsRestTemplateInterceptor implements ClientHttpRequestInterceptor {
|
||||
|
||||
@Autowired
|
||||
private PrometheusMeterRegistry prometheusMeterRegistry;
|
||||
|
||||
private Counter qpsCounter;
|
||||
|
||||
@Override
|
||||
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
|
||||
|
||||
ClientHttpResponse response = execution.execute(request, body);
|
||||
|
||||
|
||||
qpsCounter = Counter.builder("spring.cloud.rpc.restTemplate.qps")
|
||||
.description("Spring Cloud Alibaba QPS metrics when use resTemplate RPC Call.")
|
||||
.baseUnit(TimeUnit.SECONDS.name())
|
||||
.tag("sca.resTemplate.rpc", "url: " + request.getURI()
|
||||
+ " method: " + request.getMethod()
|
||||
+ " status: " + response.getStatusCode())
|
||||
.register(prometheusMeterRegistry);
|
||||
|
||||
|
||||
qpsCounter.increment();
|
||||
|
||||
return response;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.seata.web;
|
||||
|
||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author kwings6
|
||||
*/
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ConditionalOnWebApplication
|
||||
public class SeataHandlerInterceptorAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, PrometheusMeterRegistry registry) {
|
||||
return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, "");
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SeataHandlerInterceptor seataHandlerInterceptor() {
|
||||
return new SeataHandlerInterceptor();
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
com.alibaba.cloud.seata.rest.SeataRestTemplateAutoConfiguration
|
||||
com.alibaba.cloud.seata.web.SeataHandlerInterceptorConfiguration
|
||||
com.alibaba.cloud.seata.feign.SeataFeignClientAutoConfiguration
|
||||
com.alibaba.cloud.seata.web.SeataHandlerInterceptorAutoConfiguration
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2013-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.alibaba.cloud.stream.binder.rocketmq.metrics;
|
||||
|
||||
import com.alibaba.cloud.stream.binder.rocketmq.properties.RocketMQProducerProperties;
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.DistributionSummary;
|
||||
import io.micrometer.prometheus.PrometheusMeterRegistry;
|
||||
|
||||
/**
|
||||
* @author kwings6
|
||||
*/
|
||||
public final class MessageMeter {
|
||||
private MessageMeter() {
|
||||
}
|
||||
|
||||
public static DistributionSummary getMQProducerSumCounter(String destination, RocketMQProducerProperties producerProperties,
|
||||
PrometheusMeterRegistry prometheusMeterRegistry) {
|
||||
return DistributionSummary.builder("spring.cloud.alibaba.rocketmq.producer.message.sum")
|
||||
.description("Spring Cloud Alibaba RocketMQ Producer Message Sum")
|
||||
.tag("destination", destination)
|
||||
.tag("nameServer", producerProperties.getGroup())
|
||||
.tag("group", producerProperties.getGroup())
|
||||
.tag("producerType", producerProperties.getProducerType())
|
||||
.tag("sendType", producerProperties.getSendType())
|
||||
.tag("accessChannel", producerProperties.getAccessChannel())
|
||||
.register(prometheusMeterRegistry);
|
||||
}
|
||||
|
||||
public static DistributionSummary getMQProducerFailCounter(RocketMQProducerProperties producerProperties,
|
||||
PrometheusMeterRegistry prometheusMeterRegistry) {
|
||||
return DistributionSummary.builder("spring.cloud.alibaba.rocketmq.producer.message.fail.sum")
|
||||
.description("Spring Cloud Alibaba RocketMQ Producer Message Fail Sum")
|
||||
.tag("nameServer", producerProperties.getGroup())
|
||||
.tag("group", producerProperties.getGroup())
|
||||
.tag("producerType", producerProperties.getProducerType())
|
||||
.tag("sendType", producerProperties.getSendType())
|
||||
.tag("accessChannel", producerProperties.getAccessChannel())
|
||||
.register(prometheusMeterRegistry);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static Counter getMQConsumerSumCounter(String topic, PrometheusMeterRegistry prometheusMeterRegistry) {
|
||||
return Counter.builder("spring.cloud.alibaba.rocketmq.consumer.message.success.sum")
|
||||
.description("Spring Cloud Alibaba RocketMQ Message Consumer Success Sum")
|
||||
.tag("topic", topic)
|
||||
.register(prometheusMeterRegistry);
|
||||
}
|
||||
}
|