服务注册与发现
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eureka-serverartifactId>
<version>1.4.7.RELEASEversion>
dependency>
dependencies>
application.yml
server:
port: 7001
# Eureka
eureka:
instance:
hostname: localhost # 服务端名称
client:
register-with-eureka: false # 是否注册自己
fetch-registry: false # 是否获取信息,为false表示自己为注册中心
service-url:
# 这里应该是其他集群的地址,如果单机部署就填自己
defaultZone: http://127.0.0.1:7002/eureka/,http://127.0.0.1:7003/eureka/
启动类
@SpringBootApplication
@EnableEurekaServer // 需要加上启动注解
public class Eureka7001 {
public static void main(String[] args) {
SpringApplication.run(Eureka7001.class,args);
}
}
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eurekaartifactId>
<version>1.4.7.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
application.yml
server:
port: 8001
spring:
application:
name: springcloud-provider-dept # 这个name是服务的名称,也是服务的标识,多个相同的服务可以重名
# Eureka
eureka:
client:
service-url:
# 所有注册中心集群的地址
defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/,http://127.0.0.1:7003/eureka/
instance:
instance-id: ${spring.application.name}:${server.port} # 修改eureka默认描述
# 需要spring-boot-starter-actuator,这里的信息或出现在eureka监控详情信息里
info:
app.name: king-springcloud
app.company.name: king-company
启动类
@SpringBootApplication
@EnableEurekaClient
public class Eureka7001 {
public static void main(String[] args) {
SpringApplication.run(Eureka7001.class,args);
}
}
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-eurekaartifactId>
<version>1.4.7.RELEASEversion>
dependency>
application.yml
server:
port: 8001
spring:
application:
name: springcloud-consumer-dept # 这个name是服务的名称,也是服务的标识,多个相同的服务可以重名
# Eureka
eureka:
client:
register-with-eureka: false # 是否注册自己
service-url:
defaultZone: http://127.0.0.1:7001/eureka/,http://127.0.0.1:7002/eureka/,http://127.0.0.1:7003/eureka/
启动类
@SpringBootApplication
@EnableEurekaClient
public class DeptConsumer80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80.class,args);
}
}
启动类
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class DeptProvider8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001.class, args);
}
}
使用
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
/**
* 可以用这个类获取一些信息
* getServices
* getInstances => instance.getServiceId()
* instance.getHost()
* instance.getPort()
* instance.isSecure()
* instance.getUri())
*/
@Autowired
private DiscoveryClient discoveryClient;
/**
* 注册进来的微服务,想办法获取一些信息
*/
@RequestMapping("/getinfo")
public Object getInfo() {
List<String> services = discoveryClient.getServices();
System.out.println("discoveryClient=>service:");
for (String service : services) {
System.out.println(service);
}
System.out.println();
System.out.println("discoveryClient=>instance:");
List<ServiceInstance> instances = discoveryClient.getInstances("springcloud-provider-dept-8001");
for (ServiceInstance instance : instances) {
System.out.println(instance.getInstanceId() + "\t" +
instance.getServiceId() + "\t" +
instance.getHost() + "\t" +
instance.getPort() + "\t" +
instance.isSecure() + "\t" +
instance.getUri());
}
return this.discoveryClient;
}
}
在服务器搭建好后
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-zookeeper-discoveryartifactId>
<exclusions>
<exclusion>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>org.apache.zookeepergroupId>
<artifactId>zookeeperartifactId>
<version>3.5.5version>
dependency>
application.yml
server:
port: 8001
spring:
application:
name: springcloud-provider-dept
cloud:
zookeeper:
connect-string: 127.0.0.1:2181
使用它首先要注册一个Bean
@Configuration
public class ConfigBean {
/**
* 导入ribbon后,实现客户端负载均衡,新版的Eureka集成了ribbon
* */
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
使用
@RestController
public class DeptController {
@Autowired
private RestTemplate restTemplate;
// 这里是要调用的服务的名,也可以是一个具体的url
private static final String REST_URL_PREFIX = "http://SPRINGCLOUD-PROVIDER-DEPT";
@RequestMapping("/dept/getDeptById/{id}")
public Dept get(@PathVariable("id") Long id) {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/getDeptById/" + id, Dept.class);
}
}
启动类
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
public class DeptProvider8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider8001.class, args);
}
}
使用
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
/**
* 可以用这个类获取一些信息
* getServices
* getInstances => instance.getServiceId()
* instance.getHost()
* instance.getPort()
* instance.isSecure()
* instance.getUri())
*/
@Autowired
private DiscoveryClient discoveryClient;
/**
* 注册进来的微服务,想办法获取一些信息
*/
@RequestMapping("/getinfo")
public Object getInfo() {
List<String> services = discoveryClient.getServices();
System.out.println("discoveryClient=>service:");
for (String service : services) {
System.out.println(service);
}
System.out.println();
System.out.println("discoveryClient=>instance:");
List<ServiceInstance> instances = discoveryClient.getInstances("springcloud-provider-dept-8001");
for (ServiceInstance instance : instances) {
System.out.println(instance.getInstanceId() + "\t" +
instance.getServiceId() + "\t" +
instance.getHost() + "\t" +
instance.getPort() + "\t" +
instance.isSecure() + "\t" +
instance.getUri());
}
return this.discoveryClient;
}
}
linux下安装后运行consul
consul agent -dev
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-consul-discoveryartifactId>
dependency>
application.yml
server:
port: 8001
spring:
application:
name: springcloud-provider-dept
cloud:
consul:
host: localhost
port: 8500
discovery:
service-name:${spring.application.name}
配置类(配置类不能在主启动类同级文件夹下)
@Configuration
public class MyRule{
@Bean
public IRule setRule(){
return new RandomRule();
}
}
主启动类
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "springcloud-consumer-dept", configuration = MyRule.class)
public class DeptConsumer80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer80.class, args);
}
}
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
启动类
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class DeptConsumerOpenFeign80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerOpenFeign80.class, args);
}
}
使用方法
@Service
@FeignClient(value = "springcloud-provider-dept")
public interface DeptFeignClient {
@PostMapping("/dept/add")
public boolean addDept(String name);
@GetMapping("/dept/getDeptById/{id}")
public Dept getDeptById(@PathVariable("id") Long id);
@GetMapping("/dept/getDeptList")
public List<Dept> getDeptList();
}
application.yml
logging:
level:
# feign日志以什么级别监听哪个接口
com.king.springcloud.service.DeptConsumerOpenFeign80: debug
FeignConfig.java
package com.king.springcloud.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>
服务端
启动类
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class SpringcloudProviderDeptHystrix8001 {
public static void main(String[] args) {
SpringApplication.run(SpringcloudProviderDeptHystrix8001.class, args);
}
}
方法
@HystrixCommand(fallbackMethod = "degradeHandler",commandProperties = {
@HystrixProperty(name="execution.isolation.thread.timeoutInMillisecond",value="5000")
})
@GetMapping(value = "/timeout/ok")
public String timeoutOk() {
int timeout = 3;
try {
TimeUnit.SECONDS.sleep(timeout);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Thread.currentThread().getName() + port + ":请求成功!!!" + "超时(s):" + timeout;
}
public String degradeHandler() {
return Thread.currentThread().getName() + port + "服务异常";
}
application.yml
feign:
hystrix:
enabled: true
启动类
@SpringBootApplication
@EnableEurekaClient
@EnableHystrix
public class SpringcloudProviderDeptHystrix8001 {
public static void main(String[] args) {
SpringApplication.run(SpringcloudProviderDeptHystrix8001.class, args);
}
}
方法部分与服务端相同
除了个别重要核心业务,其他的通过 @DefaultProperties(defaultFallback = “”) 统一处理
@RestController
@DefaultProperties(defaultFallback = "globalHandler")
public class DeptController {
@Autowired
private DeptFeignClient deptFeignClient;
@HystrixCommand
@RequestMapping("/dept/getDeptById/{id}")
public Dept get(@PathVariable("id") Long id) {
return deptFeignClient.getDeptById(id);
}
@HystrixCommand
@RequestMapping("/dept/add")
public boolean add(Dept dept) {
return deptFeignClient.addDept(dept.getName());
}
@HystrixCommand
@RequestMapping("/dept/getDeptList")
public List<Dept> getList() {
System.out.println(123);
return deptFeignClient.getDeptList();
}
@HystrixCommand(fallbackMethod = "coreHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
})
@GetMapping("/dept/timeout")
public String feignTimeout() {
return deptFeignClient.feignTimeout();
}
public String coreHandler() {
return "服务器错误,请稍后重试!!!";
}
public String globalHandler() {
return "服务器错误,请稍后重试.";
}
}
先写一个类用来处理FeignClient,同时implement接口
@Component
public class DeptFeignClientFallback implements DeptFeignClient {
@Override
public boolean addDept(String name) {
return false;
}
@Override
public Dept getDeptById(Long id) {
return new Dept();
}
@Override
public List<Dept> getDeptList() {
return new ArrayList<>();
}
@Override
public String feignTimeout() {
return "超时!";
}
}
在FeignClient中配置fallback
@Service
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallback = DeptFeignClientFallback.class)
public interface DeptFeignClient {
@PostMapping("/dept/add")
public boolean addDept(String name);
@GetMapping("/dept/getDeptById/{id}")
public Dept getDeptById(@PathVariable("id") Long id);
@GetMapping("/dept/getDeptList")
public List<Dept> getDeptList();
@GetMapping("/dept/timeout")
public String feignTimeout();
}
服务降级->服务熔断->恢复调用链路
@HystrixCommand(fallbackMethod = "circuitBreakerHandler", commandProperties = {
@HystrixProperty(name = "circuitBreaker.enabled", value = "true"),//是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),//请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "5000"),//熔断后多久半启动
@HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "10000"),//时间窗口
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")//失败率达到多少后断路
})
@GetMapping(value = "/breaker/{id}")
public String circuitBreaker(@PathVariable(value = "id") String id) throws Exception {
if (Integer.parseInt(id) < 0) {
throw new Exception();
}
return Thread.currentThread().getName() + "成功" + "-id-:" + id;
}
public String circuitBreakerHandler(@PathVariable(value = "id") String id) {
return Thread.currentThread().getName() + "失败" + "-id-:" + id;
}
/* --------------统计相关------------------*/
// 统计滚动的时间窗口,默认:5000毫秒(取自circuitBreakerSleepWindowInMilliseconds)
private final HystrixProperty metricsRollingStatisticalWindowInMilliseconds;
// 统计窗口的Buckets的数量,默认:10个,每秒一个Buckets统计
private final HystrixProperty metricsRollingStatisticalWindowBuckets; // number of buckets in the statisticalWindow
// 是否开启监控统计功能,默认:true
private final HystrixProperty metricsRollingPercentileEnabled;
/* --------------熔断器相关------------------*/
// 熔断器在整个统计时间内是否开启的阀值,默认20。也就是在metricsRollingStatisticalWindowInMilliseconds(默认10s)内至少请求20次,熔断器才发挥起作用
private final HystrixProperty circuitBreakerRequestVolumeThreshold;
// 熔断时间窗口,默认:5秒.熔断器中断请求5秒后会进入半打开状态,放下一个请求进来重试,如果该请求成功就关闭熔断器,否则继续等待一个熔断时间窗口
private final HystrixProperty circuitBreakerSleepWindowInMilliseconds;
//是否启用熔断器,默认true. 启动
private final HystrixProperty circuitBreakerEnabled;
//默认:50%。当出错率超过50%后熔断器启动
private final HystrixProperty circuitBreakerErrorThresholdPercentage;
//是否强制开启熔断器阻断所有请求,默认:false,不开启。置为true时,所有请求都将被拒绝,直接到fallback
private final HystrixProperty circuitBreakerForceOpen;
//是否允许熔断器忽略错误,默认false, 不开启
private final HystrixProperty circuitBreakerForceClosed;
/* --------------信号量相关------------------*/
//使用信号量隔离时,命令调用最大的并发数,默认:10
private final HystrixProperty executionIsolationSemaphoreMaxConcurrentRequests;
//使用信号量隔离时,命令fallback(降级)调用最大的并发数,默认:10
private final HystrixProperty fallbackIsolationSemaphoreMaxConcurrentRequests;
/* --------------其他------------------*/
//使用命令调用隔离方式,默认:采用线程隔离,ExecutionIsolationStrategy.THREAD
private final HystrixProperty executionIsolationStrategy;
//使用线程隔离时,调用超时时间,默认:1秒
private final HystrixProperty executionIsolationThreadTimeoutInMilliseconds;
//线程池的key,用于决定命令在哪个线程池执行
private final HystrixProperty executionIsolationThreadPoolKeyOverride;
//是否开启fallback降级策略 默认:true
private final HystrixProperty fallbackEnabled;
// 使用线程隔离时,是否对命令执行超时的线程调用中断(Thread.interrupt())操作.默认:true
private final HystrixProperty executionIsolationThreadInterruptOnTimeout;
// 是否开启请求日志,默认:true
private final HystrixProperty requestLogEnabled;
//是否开启请求缓存,默认:true
private final HystrixProperty requestCacheEnabled; // Whether request caching is enabled.
//请求合并是允许的最大请求数,默认: Integer.MAX_VALUE
private final HystrixProperty maxRequestsInBatch;
//批处理过程中每个命令延迟的时间,默认:10毫秒
private final HystrixProperty timerDelayInMilliseconds;
//批处理过程中是否开启请求缓存,默认:开启
private final HystrixProperty requestCacheEnabled;
/* 配置线程池大小,默认值10个 */
private final HystrixProperty corePoolSize;
/* 配置线程值等待队列长度,默认值:-1 建议值:-1表示不等待直接拒绝,测试表明线程池使用直接决绝策略+ 合适大小的非回缩线程池效率最高.所以不建议修改此值。 当使用非回缩线程池时,queueSizeRejectionThreshold,keepAliveTimeMinutes 参数无效 */
private final HystrixProperty maxQueueSize;
applicatoin.yml
server:
port: 9001
启动类
@SpringBootApplication
@EnableHystrixDashboard
public class Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Bootstrap.class,args);
}
}
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboardartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
访问的微服务地址
http://localhost:8001/hystrix.stream
pom.xml
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
启动类
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class SpringcloudProviderDeptHystrix8001 {
public static void main(String[] args) {
SpringApplication.run(SpringcloudProviderDeptHystrix8001.class, args);
}
@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;
}
}
路由与断言
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
转发可以通过写配置文件,也可以通过写配置类实现
application.yml
spring:
application:
name: springcloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true # 通过注册中心,使用服务名转发
routes:
- id: dept-provider-route
uri: lb://springcloud-provider-dept
# uri: http://localhost:8001 # 转发地址
predicates:
- Path=/dept/getDeptById/** # 断言
- id: dept-provider-route2
uri: lb://springcloud-provider-dept
# uri: http://localhost:8001
predicates:
- Path=/dept/getDeptList
Gateway.java
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("dept-provider-route",
r -> r.path("/guonei")
.uri("https://news.baidu.com/guonei")).build();
return routes.build();
}
}
predicates常用
predicates:
- Path=/dept/getDeptById/** # 断言
- After=2021-09-21T21:41:13.154920100+08:00[Asia/Shanghai] # 在这个时间之后路由生效
- Before=2021-09-21T21:41:13.154920100+08:00[Asia/Shanghai] # 在这个时间之前路由生效
# 在这个时间之间路由生效
- Between=2021-09-21T21:41:13.154920100+08:00[Asia/Shanghai],2021-09-21T22:41:13.154920100+08:00[Asia/Shanghai]
- Cookie=username,admin # 带有cookie可以访问,参数:name,正则
- Header=X-Request,/d+ # 带有header可以访问,参数:name,正则
- Host=**.baidu.com # 指定host 例如->www.baidu.com,news.baidu.com
- Method=GET # 指定访问方法
- Query=username,admin # 带有指定参数可以访问,参数:key,正则
MyLogGlobalFilter.java
@Component
@Slf4j
public class MyLogGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("=====================MyLogGlobalFilter====================="+new Date());
String uname = exchange.getRequest().getQueryParams().getFirst("uname");
if(uname == null){
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-config-serverartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
application.yml
server:
port: 3344
spring:
application:
name: spring-cloud-config-center
cloud:
config:
server:
git:
uri: https://gitee.com/auroranb/springcloud-config.git
search-paths:
- springcloud-config
username: [email protected]
password: favour1.
label: master
启动类
@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class Bootstrap {
public static void main(String[] args) {
SpringApplication.run(Bootstrap.class, args);
}
}
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-configartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bootstrapartifactId>
dependency>
bootstrap.yml
# master分支下的config-dev.yml
server:
port: 3355
spring:
cloud:
config:
label: master
name: config
profile: dev
uri: http://localhost:3344 # config server地址
application:
name: spring-cloud-cofig-client
动态刷新配置
bootstrap.yml
# master分支下的config-dev.yml
server:
port: 3355
spring:
cloud:
config:
label: master
name: config
profile: dev
uri: http://localhost:3344 # config server地址
application:
name: spring-cloud-cofig-client
# 暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
使用处添加@RefreshScope注解
@RestController
@RefreshScope
public class ConfigController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo(){
return configInfo;
}
}
配置更新后向client端发送post请求更新配置
curl -X POST ""http://localhost:3355/actuator/refresh"
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bus-amqpartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
application.yml
management:
endpoints:
web:
exposure:
include: 'bus-refresh'
spring:
rabbitmq:
host: 8.136.225.205
port: 5672
username: guest
password: guset
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bus-amqpartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
bootstrap.yml
management:
endpoints:
web:
exposure:
include: "*"
spring:
rabbitmq:
host: 8.136.225.205
port: 5672
username: guest
password: guset
向config-server发送post
curl -X POST "http://${配置中心ip:port}/actuator/bus-refresh"
定点更新
curl -X POST "http://${配置中心ip:port}/actuator/bus-refresh/${config-client-name}:${prot}"
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-stream-rabbitartifactId>
dependency>
application.yml
spring:
application:
name: cloud-stream-provider
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合 可以随便写什么
type: rabbit # 底层消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
host: 8.136.225.205
port: 5672
username: guest
password: guest
virtual-host: /
bindings: # 服务的整合处理 消费者配置,在此绑定
# 消息生产者配置(哪个提供者服务需要就配置)
output: # 这个名字是一个通道的名称
destination: my-exchange # 表示要使用的Exchange交换机名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置binder
management:
health:
rabbit:
enable: false
使用
@EnableBinding(Source.class) // 上文中bindings下的output对应Source类中@Output中的内容
public class DefaultMessageProviderImpl{
@Resource
public MessageChannel output;
public String send() {
String uuid = UUID.randomUUID().toString();
output.send(MessageBuilder.withPayload(uuid).build());
System.out.println("uuid--"+uuid);
return uuid;
}
}
application.yml
spring:
application:
name: cloud-stream-provider
cloud:
stream:
binders: # 在此处配置要绑定的rabbitmq的服务信息;
defaultRabbit: # 表示定义的名称,用于于binding整合 可以随便写什么
type: rabbit # 底层消息组件类型
environment: # 设置rabbitmq的相关的环境配置
spring:
rabbitmq:
host: 8.136.225.205
port: 5672
username: guest
password: guest
virtual-host: /
bindings: # 服务的整合处理 消费者配置,在此绑定
# 消息生产者配置(哪个提供者服务需要就配置)
input: # 这个名字是一个通道的名称
destination: my-exchange # 表示要使用的Exchange交换机名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置binder
management:
health:
rabbit:
enable: false
使用
EnableBinding(Sink.class) //上文中bindings下的input对应Sink.class中@Input中的参数
@Component
public class ReceiveMessageListenerController {
@Value("${server.port}")
private String port;
@StreamListener(Sink.INPUT)
public void input(Message<String> message){
System.out.println("消费者1 --- 消息:" + message.getPayload() + "\t port:" + port );
}
}
通过定义bindings下的每个队列的group
相同的group一起消费消息
不同的group分别消费消息
....
bindings: # 服务的整合处理 消费者配置,在此绑定
# 消息生产者配置(哪个提供者服务需要就配置)
input: # 这个名字是一个通道的名称
destination: my-exchange # 表示要使用的Exchange交换机名称定义
content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
binder: defaultRabbit # 设置要绑定的消息服务的具体设置binder
group: mygroup
同时设置了group属性可以完成数据持久化,会消费未启动前队列中的堆存的消息
原理是,exchange数据发送到队列中,没有froup重启没有设置分组,会重新创建队列并监听,设置了group还是监听原来队列。
首先安装zipkin
docker安装或本地安装
docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin /bin/bash
在需要监控的服务上的application.yml上加
spring:
zipkin:
base-url: http://localhost:9411
sleuth:
sampler:
probability: 1
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-stream-zipkinartifactId>
dependency>
打开zipkin部署地址的9411查看
下载后启动进入bin目录
startup.cmd -m standalone
打开管理页面
http://localhost:8848
pom.xml
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
启动类
package com.king.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class AlibabaProvider9901 {
public static void main(String[] args) {
SpringApplication.run(AlibabaProvider9901.class,args);
}
}
application.yml
server:
port: 9901
spring:
application:
name: spring-cloud-alibaba-provider
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
management:
endpoints:
web:
exposure:
include: '*'
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-ribbonartifactId>
<version>2.2.9.RELEASEversion>
dependency>
application.yml
server:
port: 9901
spring:
application:
name: spring-cloud-alibaba-provider
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
management:
endpoints:
web:
exposure:
include: '*'
config.java
@Configuration
public class BeanConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
使用
@RestController
public class ConsumerController {
public static final String SERVICE_NAME = "http://spring-cloud-alibaba-provider";
@Resource
private RestTemplate restTemplate;
@RequestMapping("/consumer/nacos/{id}")
public String consume(@PathVariable("id") String id){
String url = SERVICE_NAME + "/provider/nacos/" + id;
System.out.println(url);
return restTemplate.getForObject( url , String.class);
}
}
pom.xml
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-bootstrapartifactId>
dependency>
bootstrap.yml
server:
port: 3366
spring:
application:
name: spring-cloud-alibaba-config-client
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
# namespace: 此处可以填写命名空间的id来指定命名空间
# group: 此处可以指定分组
management:
endpoints:
web:
exposure:
include: '*'
application.yml
spring:
profiles:
active: dev
在配置中心添加配置,Data Id格式
${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.discovery.server-addr}
nacos目前支持msql
首先找到nacos的conf目录下的sql脚本并执行
修改application.properties,加上如下配置
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
db.user.0=root
db.password.0=root
在多台linux服务器上下载nacos
cluster.conf
123.456.789.1:8848
123.456.789.2:8848
123.456.789.3:8848
修改application.properties,加上如下配置
spring.datasource.platform=mysql
### Count of DB:
db.num=1
### Connect URL of DB:
db.url.0=jdbc:mysql://123.456.789.4:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=root
下载控制台:https://github.com/alibaba/Sentinel/releases
启动
java -jar -DServer.port=<port> sentinel-dashboard-<version>.jar
控制台账号密码均为sentinel
pom.xml
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
application.yml
server:
port: 8401
spring:
application:
name: sentinel-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
sentinel:
transport:
dashboard: 127.0.0.1:8080
port: 8719
management:
endpoints:
web:
exposure:
include: '*'
@SentinelResource
@RequestMapping("/byResource")
@SentinelResource(value = "byResource", blockHandler = "byResourceHandler")
public CommonResult byResource() {
return new CommonResult(0, "请求成功", new Dept(1000, "dept1"));
}
public CommonResult byResourceHandler(BlockException blockException) {
return new CommonResult(100, "请求失败 -- " + blockException.getClass().getCanonicalName(), null);
}
@RequestMapping("/byUrl")
@SentinelResource(value = "byUrl")
public CommonResult byUrl() {
return new CommonResult(0, "byUrl请求成功", new Dept(1000, "dept1"));
}
@RequestMapping("/byBlockHandler")
@SentinelResource(value = "byBlockHandler",
blockHandlerClass = CustomBlockHandler.class,
blockHandler = "blockHandler2"
)
public CommonResult byBlockHandler() {
return new CommonResult(0, "byBlockHandler请求成功", new Dept(1000, "dept1"));
}
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
application.yml
feign:
sentinel:
enabled: true
剩下部分与Netflix部分openfeign相同
pom.xml
<dependency>
<groupId>com.alibaba.cspgroupId>
<artifactId>sentinel-datasource-nacosartifactId>
dependency>
application.yml
spring:
application:
name: spring-cloud-alibaba-consumer
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
sentinel:
transport:
dashboard: 127.0.0.1:8080
port: 8719
datasource: # 持久化配置
ds1:
nacos: # 使用nacos进行持久化
server-addr: 127.0.0.1:8848 # nacos的地址
dataId: ${spring.application.name} # 储存配置的名称,(nacos中要有相应的配置!!!)
groupId: DEFAULT_GROUP # 分组
#namespace:..... # 不配置则是默认命名空间
data-type: json # 配置文件的类型
rule-type: flow #
写入nacos的配置,具体如何配置查看官网的流量控制、熔断降级、热点参数限流、系统自适应限流的详细配置
[
{
....
},
{
....
}
]
下载seata:https://github.com/seata/seata/releases
打开conf目录,修改file.conf
创建相应的seata数据库
这里sql语句在conf文件夹下README.md中(标题链接)
registry {
# file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
type = "nacos"
nacos {
application = "seata-server"
serverAddr = "127.0.0.1:8848"
group = "SEATA_GROUP"
namespace = ""
cluster = "default"
username = "nacos"
password = "nacos"
}
.....
}
-- 注意此处0.3.0+ 增加唯一索引 ux_undo_log
CREATE TABLE `undo_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`branch_id` bigint(20) NOT NULL,
`xid` varchar(100) NOT NULL,
`context` varchar(128) NOT NULL,
`rollback_info` longblob NOT NULL,
`log_status` int(11) NOT NULL,
`log_created` datetime NOT NULL,
`log_modified` datetime NOT NULL,
`ext` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-seataartifactId>
<exclusions>
<exclusion>
<groupId>io.seatagroupId>
<artifactId>seata-allartifactId>
exclusion>
exclusions>
dependency>
<dependency>
<groupId>io.seatagroupId>
<artifactId>seata-allartifactId>
<version>1.4.2version>
dependency>
server:
port: 9991
spring:
application:
name: spring-cloud-seata-order
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
alibaba:
seata:
tx-service-group: my_tx_group # 此处必须与file.conf中配置的事务组名称一致
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://47.108.93.159:3307/db_order
management:
endpoints:
web:
exposure:
include: '*'
将file.conf和registry.conf放在每个用到全局事务的微服务的resource目录下(如果配置了nacosconfig就不需要)
配置代理数据源,由于最终是由seata进行全局事务管理,所以要将数据源给seata代理
在业务代码上加上@GlobalTransactional并指定事务组