| cloud-config-center-3344 | Конфигурационный центр (Config-Server), сервисная шина (BUS) | | cloud-config-client-3355 | Конфигурационный клиент 1, конфигурационный центр (Config), сервисная шина (BUS) | | cloud-config-client-3356 | Конфигурационный клиент 2, конфигурационный центр (Config), сервисная шина (BUS) | | cloud-stream-provider-rabbitmq8801 | Источник сообщений, управляемый потоком данных (Stream) | | cloud-stream-provider-rabbitmq8802 | Получатель сообщений 1, управляемый потоком данных (Stream) | | cloud-stream-consumer-rabbitmq8803 | Получатель сообщений 2, управляемый потоком данных (Stream) | | cloudalibaba-config-nacos-client3377 | Клиент конфигурационного центра Nacos, конфигурационный центр (Nacos), сервис регистрации (Nacos) | | cloudalibaba-provider-nacos-payment9001 | Поставщик услуг через Nacos регистрирует услугу 1, сервис регистрации (Nacos) | | cloudalibaba-provider-nacos-payment9002 | Поставщик услуг через Nacos регистрирует услугу 2, сервис регистрации (Nacos) | | cloudalibaba-provider-nacos-payment9003 | Поставщик услуг имитирует запрос услуги через Nacos 1, сервис регистрации (Nacos) | | cloudalibaba-provider-nacos-payment9004 | Поставщик услуг имитирует запрос услуги через Nacos 2, сервис регистрации (Nacos) | | cloudalibaba-sentinel-service8401 | Пример использования Sentinel для ограничения потока и разрыва соединения с сервисом | | cloudalibaba-consumer-nacos-order84 | Потребитель использует Feign и Sentinel, сервис регистрации (Nacos), сервис вызова (Openfeign), балансировка нагрузки (Rabbin) | | cloudalibaba-seata-order-service12001 | Микросервис для размещения заказа в рамках распределённой транзакции, сервис регистрации (Nacos), сервис вызова (Openfeign), балансировка нагрузки (Rabbin) | | cloudalibaba-seata-storage-service12002 | Микросервис хранилища в рамках распределённой транзакции, сервис регистрации (Nacos), сервис вызова (Openfeign), балансировка нагрузки (Rabbin) | | cloudalibaba-seata-account-service12003 | Микросервис учётной записи в рамках распределённой транзакции, сервис регистрации (Nacos), сервис вызова (Openfeign), балансировка нагрузки (Rabbin). |
<!--eureka-server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--Рекомендуется использовать вместе с горячим развертыванием-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #Имя экземпляра сервера Eureka
client:
#false означает не регистрироваться в реестре
register-with-eureka: false
#false означает, что сам является реестром, и не нужно искать сервисы
fetch-registry: false
service-url:
#Настройка адреса взаимодействия с сервером Eureka, требуется для поиска и регистрации сервисов
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #Одноузловая версия, указывает на себя
#defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #Кластерная версия
server:
#Отключить механизм самозащиты Eureka, чтобы гарантировать, что недоступные сервисы будут немедленно удалены
enable-self-preservation: false
eviction-interval-timer-in-ms: 2000
@SpringBootApplication
@EnableEurekaServer
public class EurekaMain7001 {
public static void main(String[] args) {
SpringApplication.run(EurekaMain7001.class, args);
}
}
Соответствующие проекты: cloud-eureka-server7001, cloud-eureka-server7002 name: cloud-payment-service
eureka:
client:
#表示是否将自己注册进EurekaServer,默认为true
register-with-eureka: true
#是否从EurekaServer中抓取已有的注册信息,默认为true。单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
defaultZone: http://localhost:7001/eureka #单机版
#defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
instance:
instance-id: payment8001 #修改Status名称
prefer-ip-address: true
#Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认30)
lease-renewal-interval-in-seconds: 10
#Eureka服务端在收到最后一次心跳后等待的时间上限,单位为秒(默认90),超时剔除服务
lease-expiration-duration-in-seconds: 60
3)启动类添加注解@EnableDiscoveryClient(推荐)或者@EnableEurekaClient
@SpringBootApplication
@EnableDiscoveryClient //Discovery服务发现
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class, args);
}
}
对应项目:cloud-provider-payment8001、cloud-provider-payment8002等
1)导入依赖
<!-- SpringBoot整合zookeeper客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<!-- 先排除自带的zookeeper -->
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 添加本机zookeeper3.4.14版本 -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.14</version>
</dependency>
2)application.yml示例
server:
port: 8004
#服务别名——注册到zookeeper注册中心的名称
spring:
application:
name: cloud-provider-payment
cloud:
zookeeper:
connect-string: 127.0.0.1:2181
3)启动类添加注解@EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient //该注解用于向使用zookeeper作为注册中心时注册服务
public class ZkPaymentMain8004 {
public static void main(String[] args) {
SpringApplication.run(ZkPaymentMain8004.class, args);
}
}
对应项目:cloud-provider-zk-payment8004
1)导入依赖
<!-- consul软件官方下载:https://www.consul.io/downloads.html
开发模式启动:consul agent -dev
验证:浏览器访问 http://localhost:8500
若提示:
Consul returned an error. You may have visited a URL that is loading an unknown resource,so you can try going back to the root or try re-submitting your ACL Token/SecretID by going back to ACLs.
错误请使用其他浏览器访问试试
-->
<!--consul版服务提供方-->
<!--SpringCloud consul-server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
2)application.yml示例
server:
port: 8006
spring:
application:
name: consul-provider-payment
#consul注册中心地址
cloud:
consul:
host: localhost
port: 8500
discovery:
#hostname: 127.0.0.1
service-name: ${spring.application.name}
3)启动类添加注解@EnableDiscoveryClient
@SpringBootApplication
@EnableDiscoveryClient
public class ConsulPaymentMain8006 {
public static void main(String[] args) {
SpringApplication.run(ConsulPaymentMain8006.class, args);
}
}
对应项目:cloud-provider-consul-payment8006 Доступность и фильтрация правил
AvailabilityFilteringRule: сначала отфильтровать неисправные экземпляры, затем выбрать экземпляры с меньшей степенью параллелизма.
ZoneAvoidanceRule: правило по умолчанию, комплексная оценка производительности сервера в зоне и выбор сервера на основе его доступности.
2. Запуск класса с добавлением аннотации @RibbonClient
@SpringBootApplication
@EnableDiscoveryClient
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = MySelfRule.class)//启用Ribbon
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
}
Если использовать RestTemplate напрямую с использованием правила циклического перебора, можно непосредственно применить аннотацию @LoadBalanced к классу конфигурации.
/**
* ApplicationContextConfig
*
* @author lcry
* @date 2020/03/14 12:05
* 配置RestTemplate
*/
@Configuration
public class ApplicationContextConfig {
@Bean //相当于Spring中applicationContext.xml中<bean id="" class="">
@LoadBalanced //使用此注解赋予RestTemplate负载均衡的能力,测试自定义算法注释掉
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
Соответствующий проект: cloud-consumer-order80
Использование OpenFeign
<!-- openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://localhost:7001/eureka #单机版
#defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #集群版
#OpenFeign的超时控制配置:默认只等待1秒,超时则报错
#设置Feign客户端超时时间(OpenFeign默认支持Ribbon)
ribbon:
#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
ReadTimeout: 5000
#指的是建立连接后从服务器读取到可用资源所用的时间
connectTimeout: 5000
#开启Feign的日志客户端
logging:
level:
#Feign日志以什么级别监听哪个接口
com.lcry.springcloud.service.PaymentFeignService: debug
@SpringBootApplication
//启用Feign
@EnableFeignClients
public class FeignOrderMain80 {
public static void main(String[] args) {
SpringApplication.run(FeignOrderMain80.class, args);
}
}
/**
* FeignConfig
*
* @author lcry
* @date 2020/03/14 22:04
* Feign日志控制
*/
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel() {
/**
* 日志级别:
* NONE :不记录任何日志(默认)
* BASIC:仅记录请求方法、URL、响应状态代码以及执行时间
* HEADERS:记录BASIC级别的基础上,记录请求和响应的header
* FULL:记录请求和响应的header,body和元数据
*/
return Logger.Level.FULL;
}
}
/**
* PaymentFeignService
*
* @author lcry
*/
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE") //需要调用的目标微服务应用名称
public interface PaymentFeignService {
//Feign接口中的方法要与目标服务中的Controller中的方法完全一致,可以直接copy
@GetMapping(value = "/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
@GetMapping(value = "/payment/feign/timeout")
public String paymentFeignTimeout();
}
Соответствующий проект: cloud-consumer-feign-order80
<!--hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
server:
port: 8001
spring:
application:
name: cloud-provider-hystrix-payment
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://127.0.0.1:7001/eureka
#defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix //服务端开启Hystrix或者使用@EnableCircuitBreaker
public class HystrixPaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(HystrixPaymentMain8001.class, args);
}
}
/**
* 模拟超时3s
*
* @param id
* @return
*/
@Override
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
//超时5s或者异常直接降级
``` **5. Пример кода для обработки отказа сервиса**
public class PaymentInfo {
public String paymentInfo_TimeOut(Integer id) {
int timenum = 3;
try {
TimeUnit.SECONDS.sleep(timenum);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "Поток: " + Thread.currentThread().getName() + " id: " + id + "\t" + "O(∩_∩)O哈哈~" + " Время выполнения (сек): " + timenum;
}
public String paymentInfo_TimeOutHandler(Integer id) {
return "Поток: " + Thread.currentThread().getName() + " 8001 система занята или произошла ошибка, попробуйте позже, id: " + id + "\t" + "o(╥﹏╥)o";
}
}
**Пример использования Hystrix для обработки отказов сервисов**
@Override
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback", commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),// 是否 включить прерыватель
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),// порог количества запросов
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"), // период окна времени
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")// процент ошибок, при котором срабатывает прерыватель
})
public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
if (id < 0) {
throw new RuntimeException("id не может быть отрицательным числом");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName() + "\t" + "Вызов выполнен успешно, номер потока: " + serialNumber;
}
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) {
return "id не может быть отрицательным числом, пожалуйста, повторите попытку позже, /(ㄒoㄒ)/~~ id: " + id;
}
> *Соответствующие проекты:* cloud-provider-hystrix-payment8001, cloud-consumer-feign-order80
**2. Использование HystrixDashboard для мониторинга**
*1. Импорт зависимостей*
```xml
<!-- hystrix сервис мониторинга dashboard -->
<!--
Мониторируемый сервис должен включать web и actuator зависимости
Адрес мониторинга: http://ip: порт/hystrix
Адрес для мониторинга: http:// ip: порт/hystrix.stream
-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2. Пример файла application.yml
server:
port: 9001
3. Добавление аннотации @EnableHystrixDashboard в класс запуска
/**
* HystrixDashboardMain9001
*
* @author lcry
*/
@SpringBootApplication
@EnableHystrixDashboard //включение аннотации
public class HystrixDashboardMain9001 {
public static void main(String[] args) {
SpringApplication.run(HystrixDashboardMain9001.class, args);
}
}
4. Конфигурация на стороне мониторинга
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
/**
* Эта конфигурация предназначена для мониторинга, а не для обработки ошибок, после обновления springcloud могут возникнуть проблемы
* ServletRegistrationBean потому что по умолчанию springboot путь не "/hystrix.stream",
* достаточно настроить собственный сервлет в своём проекте
*/
@Bean
public ServletRegistrationBean getServlet() {
HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
registrationBean.setLoadOnStartup(1);
registrationBean.addUrlMappings("/hystrix.stream");
registrationBean.setName("HystrixMetricsStreamServlet");
return registrationBean;
}
5. Проверка
Посетите платформу мониторинга hystrix по адресу http://localhost:9001, адрес для мониторинга — http:// ip: порт/hystrix.stream.
Соответствующие проекты: cloud-consumer-hystrix-dashboard9001, cloud-provider-hystrix-payment8001 Соответствующий проект: cloud-config-center-3344
<!-- spring-config клиент -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
server:
port: 3355
spring:
application:
name: config-client
cloud:
# Конфигурация клиента Config
config:
label: master # имя ветки
name: config # имя конфигурации
profile: dev # имя профиля
uri: http://localhost:3344 # адрес конфигурационного центра
spring:
application:
name: config-client
cloud:
# Конфигурация клиента Config
config:
label: master # имя ветки
name: config # имя конфигурации
profile: dev # имя профиля
uri: http://localhost:3344 # адрес конфигурационного центра
Соответствующие проекты: cloud-config-client-3355, cloud-config-client-3356
<!-- Добавить поддержку RabbitMQ в шину сообщений -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
# Конфигурации RabbitMQ
rabbitmq:
host: 192.168.179.150
port: 5672
username: admin
password: admin
# Глобальное обновление POST запроса http://адрес регистрационного центра/actuator/bus-refresh
# Периодическое уведомление: (только уведомить часть) http://адрес регистрационного центра/actuator/refresh/{имя службы: порт}
# Например: http://localhost:3344/actuator/bus-refresh/config-client:3355
## Конфигурации RabbitMQ, раскрывающие конечную точку обновления bus
management:
endpoints: # Раскрывает конечную точку обновления шины
web:
exposure:
include: 'bus-refresh'
# Конфигурации RabbitMQ 15672 — это порт веб-интерфейса управления; 5672 — порт доступа MQ
rabbitmq:
host: 192.168.179.150
port: 5672
username: admin
password: admin
# Ручная настройка конечной точки обновления
management:
endpoints:
web:
exposure:
include: "*"
@RestController
@RefreshScope // Включение обновления конфигурации
public class ConfigClientController {
@Value("${server.port}")
private String serverport;
@Value("${config.info}")
private String configInfo;
// Прямой доступ к файлу конфигурации
@GetMapping("/configInfo")
public String getConfigInfo() {
return configInfo + "Порт сервера:" + serverport;
}
}
Соответствующие проекты: cloud-config-center-3344, cloud-config-center-3355, cloud-config-center-3356
<!-- Ввести stream-rabbit -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
server:
port: 8801
spring:
application:
name: cloud-stream-provider
cloud:
stream:
binders: # Здесь настраивается информация о службе, которую нужно связать;
defaultRabbit: # Указывает на определение имени, используемого для привязки
type: rabbit # Тип компонента сообщения
environment: # Настройка конфигурации среды RabbitMQ
spring:
rabbitmq:
host: 192.168.179.150
port: 5672
username: admin
password: admin
bindings: # Обработка интеграции услуг
output: # Имя канала
destination: studyExchange # Указать имя Exchange
content-type: application/json # Установить тип сообщения, здесь json, текст установлен как «text/plain»
binder: defaultRabbit # Указать конкретную конфигурацию службы для привязки
eureka:
client: # Конфигурация клиентского подключения Eureka
service-url:
defaultZone: http://localhost:7001/eureka
instance:
lease-renewal-interval-in-seconds: 2 # Установить интервал сердцебиения (по умолчанию 30 секунд)
lease-expiration-duration-in-seconds: 5 # Если сейчас превышен интервал в 5 секунд (по умолчанию 90 секунд)
instance-id: cloud-stream-provider8801 # Отображение имени хоста при отображении информации списка
prefer-ip-address: true # Путь доступа становится IP-адресом
/**
* //Определение канала отправки сообщений
*/
@EnableBinding(Source.class) //Определение канала отправки сообщений, фиксированный формат написания производителя
@Slf4j
public class MessageProviderImpl implements IMessageProvider {
``` ```
@Resource
private MessageChannel output; // 消息发送管道
@Override
public String send() {
String serial = UUID.randomUUID().toString();
output.send(MessageBuilder.withPayload(serial).build());
log.info(String.format("生成的流水号:{%s}", serial));
return serial;
}
Соответствующий проект: cloud-stream-provider-rabbitmq8801
<!-- stream-rabbit -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
server:
port: 8802
spring:
application:
name: cloud-stream-consumer
cloud:
stream:
binders: # Здесь настраивается информация о сервисе, который будет привязан к rabbitmq;
defaultRabbit: # Указывает на определение имени, которое используется при интеграции binding
type: rabbit # Тип компонента сообщения
environment: # Настройка конфигурации среды rabbitmq
spring:
rabbitmq:
host: 192.168.179.150
port: 5672
username: admin
password: admin
bindings: # Обработка интеграции сервисов
input: # Имя канала
destination: studyExchange # Указание Exchange, который нужно использовать
content-type: application/json # Установка типа сообщения, в данном случае объект json, если текст, то "text/plain"
binder: defaultRabbit # Настройка конкретной конфигурации сервиса сообщений
group: receiveclientA # Группировка для предотвращения повторного потребления и проблем с сохранением
eureka:
client: # Конфигурация клиента Eureka для регистрации
service-url:
defaultZone: http://localhost:7001/eureka
instance:
lease-renewal-interval-in-seconds: 2 # Настройка интервала сердцебиения (по умолчанию 30 секунд)
lease-expiration-duration-in-seconds: 5 # Если интервал превышает 5 секунд (по умолчанию 90 секунд)
instance-id: cloud-stream-consumer8802 # Отображение имени хоста в списке информации
prefer-ip-address: true # Путь доступа становится IP-адресом
@Component
@EnableBinding(Sink.class)
public class ReceiveMessageListenerController {
@Value("${server.port}")
private String serverPort;
@StreamListener(Sink.INPUT) // Фиксированный формат записи, соответствующий имени канала в конфигурации yml
public void input(Message<String> message) {
System.out.println("Потребитель 1,-----> Полученное сообщение: " + message.getPayload() + "\t port: " + serverPort);
}
}
Соответствующие проекты: cloud-stream-consumer-rabbitmq8802, cloud-stream-consumer-rabbitmq8802
<!--链路监控包含了sleuth+zipkin-->
<!--服务端下载地址:https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<!--引入eureka客户端eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
spring:
application:
name: cloud-payment-service
#链路监控配置,配置链路监控服务端地址
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
#采样率值介于 0 到 1 之间,1 则表示全部采集
probability: 1
Соответствующие проекты: cloud-provider-payment8001, cloud-consumer-order80
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
server:
port: 9001
spring:
application:
name: nacos-payment-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848 #配置Nacos地址,注册服务到Nacos
management:
endpoints:
web:
exposure:
include: '*'
/**
* NacosPaymentMain9001
*
* @author lcry
* @date 2020/03/16 18:03
*/ **Соответствующие проекты**: cloudalibaba-provider-nacos-payment9001, cloudalibaba-provider-nacos-payment9002.
**Использование Nacos в качестве регистрационного центра**
1. **Импорт зависимостей**:
```xml
<!-- nacos сервис можно скачать с официального сайта в виде jar и запустить напрямую -->
<!--nacos config-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--nacos discovery-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--web + actuator-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
# Активация опций конфигурационного файла
spring:
profiles:
active: dev # указывает на среду разработки
#active: test # указывает на тестовую среду
#active: prod # указывает на производственную среду
# nacos конфигурация
server:
port: 3377
spring:
application:
name: nacos-config-client
cloud:
nacos:
discovery:
server-addr: localhost:8848 # Адрес регистрационного центра Nacos
config:
server-addr: localhost:8848 # Nacos как адрес конфигурационного центра
namespace: Test-NameSpace-HA1 # Идентификатор пространства имён, для nacos1.2 можно настроить
group: DEV_GROUP # Идентификатор группы
file-extension: yaml # Указывает формат конфигурации yaml
#
# Правила именования:
# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
# nacos-config-client-dev.yaml
/**
* ConfigNacosMain3344
*
* @author lcry
* @date 2020/03/16 17:49
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ConfigNacosMain3377 {
public static void main(String[] args) {
SpringApplication.run(ConfigNacosMain3377.class, args);
}
}
/**
* NacosClientController
*
* @author lcry
*/
@RestController
@RefreshScope // Поддержка динамического обновления функций Nacos.
public class NacosClientController {
@Value("${config.info}") // Получает файл через центр конфигурации nacos
private String configInfo;
@GetMapping("/config/info")
public String getConfigInfo() {
return configInfo;
}
}
Использование Sentinel для ограничения потока
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel-datasource-nacos 后续做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
# Тестовый порт
server:
port: 8401
spring:
application:
name: cloudalibaba-sentinel-service
cloud:
nacos:
discovery:
server-addr: localhost:8848 #Адрес регистрационного центра Nacos
sentinel:
transport:
dashboard: localhost:8080 # Конфигурационный адрес Sentinel dashboard
port: 8719 # Случайный поиск адреса, если есть конфликт, то +1
# Персистентная конфигурация
# datasource:
# ds1:
# nacos:
# server-addr: localhost:8848
# dataId: cloudalibaba-sentinel-service
# groupId: DEFAULT_GROUP
# data-type: json
# rule-type: flow
management:
endpoints:
web:
exposure:
include: '*'
feign:
sentinel:
enabled: true
``` **Активация поддержки Sentinel для Feign**
1. Интерфейс сначала запрашивается один раз, затем в консоли Sentinel выполняется соответствующая операция ограничения потока.
2. Пользовательские страницы с ограничением потока и т. д. используются с помощью аннотации @SentinelResource.
```java
@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey", blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1", required = false) String p1,
@RequestParam(value = "p2", required = false) String p2) {
//int age = 10/0;
return "------testHotKey";
}
public String deal_testHotKey(String p1, String p2, BlockException exception) {
//sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
return "------deal_testHotKey,o(╥﹏╥)o";
}
@GetMapping("/rateLimit/byResource")
@SentinelResource(value = "byResource", blockHandler = "handleException")
public CommonResult byResource() {
return new CommonResult(200, "按资源名称限流测试OK", new Payment(2020L, "serial001"));
}
public CommonResult handleException(BlockException exception) {
return new CommonResult(444, exception.getClass().getCanonicalName() + "\t 服务不可用");
}
@GetMapping("/rateLimit/byUrl")
@SentinelResource(value = "byUrl")
public CommonResult byUrl() {
return new CommonResult(200, "按url限流测试OK", new Payment(2020L, "serial002"));
}
@GetMapping("/rateLimit/customerBlockHandler")
@SentinelResource(value = "customerBlockHandler", //资源名称
blockHandlerClass = CustomerBlockHandler.class, //异常自定义
blockHandler = "handlerException1") //вызов метода класса
public CommonResult customerBlockHandler() {
return new CommonResult(200, "按客戶自定义", new Payment(2020L, "serial003"));
}
/**
* @author lcry
* @date 2020/03/17 14:51
* 用户自定义处理异常类
*/
public class CustomerBlockHandler {
public static CommonResult handlerException1(BlockException exception) {
return new CommonResult(4444, "按客戶自定义,global handlerException----1");
}
public static CommonResult handlerException2(BlockException exception) {
return new CommonResult(4444, "按客戶自定义,global handlerException----2");
}}
Использование сервиса Sentinel для отката и понижения уровня обслуживания
<!-- 服务消费方,整合rabbin和feign,sentinel限流熔断等-->
<!--SpringCloud openfeign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel-datasource-nacos做持久化用到-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--SpringCloud ailibaba nacos -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--SpringCloud ailibaba sentinel -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients //整合feign
public class NacosOrderMain84 {
public static void main(String[] args) {
SpringApplication.run(NacosOrderMain84.class, args);
}
}
/**
* CircleBreakerController
*
* @author lcry
* 使用示例:
*/
@RestController
@Slf4j
public class CircleBreakerController {
public static final String SERVICE_URL = "http://nacos-payment-provider";
// 整个rabbin - restTemplate
@Resource
private RestTemplate restTemplate;
// 整合sentinel
@RequestMapping("/consumer/fallback/{id}")
//@SentinelResource(value = "fallback") //没有配置
//@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
//@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
// @SentinelResource(value = "fallback",fallback =
``` **handlerFallback**, blockHandler = "blockHandler", //разделяем пользовательские настройки
// exceptionsToIgnore = {IllegalArgumentException.class}//исключаем неконтролируемые исключения
// )
@SentinelResource(value = "fallback", //,fallback = "handlerFallback",
blockHandlerClass = CustomerBlockHandler.class, //пользовательское исключение
blockHandler = "handlerException1" //разделяем пользовательские настройки
)
public CommonResult<Payment> fallback(@PathVariable Long id) {
CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/" + id, CommonResult.class, id);
if (id == 4) {
throw new IllegalArgumentException("IllegalArgumentException,незаконный параметр исключения....");
} else if (result.getData() == null) {
throw new NullPointerException("NullPointerException,нет соответствующей записи для этого ID,пустой указатель исключения");
}
return result;
}
//этот пример является fallback
public CommonResult handlerFallback(@PathVariable Long id, Throwable e) {
Payment payment = new Payment(id, "null");
return new CommonResult<>(444, "обработчик исключений fallback,содержание исключения " + e.getMessage(), payment);
}
//этот пример является blockHandler
public CommonResult blockHandler(@PathVariable Long id, BlockException blockException) {
Payment payment = new Payment(id, "null");
return new CommonResult<>(445, "blockHandler-sentinel ограничение потока,нет такого потока: сообщение об исключении blockException", payment);
}
//OpenFeign вызов
@Resource
private PaymentService paymentService;
@GetMapping(value = "/consumer/paymentSQL/{id}")
public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id) {
return paymentService.paymentSQL(id);
}
/*
Тестирование пользовательского ограничения потока
*/
@GetMapping(value = "/consumer/paymentSQL")
@SentinelResource(value = "customerBlockHandler", //имя ресурса
blockHandlerClass = CustomerBlockHandler.class, //пользовательский обработчик исключений
blockHandler = "handlerException1") //вызов метода определенного класса
public CommonResult<Payment> paymentSQL2() {
return paymentService.paymentSQL(1L);
}
}
Соответствующий проект: cloudalibaba-consumer-nacos-order84
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--seata-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<!-- исключить встроенный, мы используем 0.9.0-->
<exclusions>
<exclusion>
<artifactId>seata-all</artifactId>
<groupId>io.seata</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>0.9.0</version>
</dependency>
<!--feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
#порт микросервиса
server:
port: 12001
spring:
application:
name: seata-order-service
cloud:
alibaba:
seata:
#настраиваемое имя группы транзакций должно соответствовать имени в seata-server
tx-service-group: fsp_tx_group
nacos:
discovery:
server-addr: localhost:8848
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/seata_order?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: lcry
#отключить feign
feign:
hystrix:
enabled: false
#OpenFeign тайм-аут управления: по умолчанию только ждать 1 секунду, тайм-аут будет сообщать об ошибке
#установить время ожидания клиента Feign (OpenFeign поддерживает Ribbon по умолчанию)
ribbon:
#означает время, необходимое для установления соединения, применимо к нормальной сетевой среде, время, затрачиваемое на соединение между двумя сторонами
ReadTimeout: 5000
#означает время от установления соединения до получения доступных ресурсов с сервера
connectTimeout: 5000
#уровень журнала
logging:
level:
io:
seata: info
#mybatis отображение
mybatis:
mapperLocations: classpath:mapper/*.xml
Настройка file.conf и register.conf, можно напрямую скопировать из Seata и поместить в каталог resources для частичного изменения
Добавить аннотацию @GlobalTransactional в бизнес-код для запуска глобальной транзакции
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )