源码

https://github.com/jiushiboy/springcloud

SpringCloud组件认知

服务注册与发现 Eureka->Nacos
服务调用1 Ribbon->LoadBalancer
服务调用2 Feign->OpenFeign
服务熔断 Hystrix->Sentinel
服务网关 Zuul->Gateway
服务配置 Config->Nacos
服务总线 Bus->Nacos

微服务模块开发步骤

建Module
改pom
写yml
主启动
业务类

开启热部署Devtools

第一步: 将依赖引入到需要热部署子模块的pom文件中

1
2
3
4
5
6
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

第二步: 添加插件依赖到父工程pom中

1
2
3
4
5
6
7
8
9
10
11
12
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<fork>true</fork>
<addResources>true</addResources>
</configuration>
</plugin>
</plugins>
</build>

第三步: 在IDEA的Settings->Build,Execution,Deployment->compiler中勾选

  • √ Automatically show first error in editor
  • √Display notification on build completion
  • √Build project automatically
  • √Compile independent modules in parallel
  • 小伙伴们千万别忘记勾选哦~

第四步: 在子模块的pom文件中
使用Shift+Ctrl+Alt+/ 选中Registry 然后找到对应选项

  • Compiler.automake.allow.when.app.running选项打勾
  • actionSystem.assertFocusAccessFromEdt
  • 然后重启IDEA修改内容则会自动重启服务

Eureka的集群搭建

文字介绍我就不跟大家多bb了,因为我也是复制的

  • 服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址,然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。
  • 当服务注册中心Eureka Server检测到服务提供者因为宕机、网络原因不可用时,则在服务注册中心将服务置为DOWN状态,并把当前服务提供者状态向订阅者发布,订阅过的服务消费者更新本地缓存。
  • 服务提供者在启动后,周期性(默认30秒)向Eureka Server发送心跳,以证明当前服务是可用状态。Eureka Server在一定的时间(默认90秒)未收到客户端的心跳,则认为服务宕机,注销该实例。
  • 处于不同节点的eureka通过Replicate进行数据同步
  • Application Service为服务提供者
  • Application Client为服务消费者
  • Make Remote Call完成一次服务调用

正题开始 —> 集群搭建
第一步:新建二个或者三个Eureka服务,如果不会请重新学去学习一下再来看;
第二步:修改电脑映射配置,默认地址在:C:\Windows\System32\drivers\etc\hosts

1
2
3
4
5
#eureka start  你有多少个服务端就可以设置多少个映射
127.0.0.1 eureka7001.com
127.0.0.1 eureka7002.com
127.0.0.1 eureka7003.com
#eureka end

第三步: 配置yml文件,分别是三台eureka服务器的配置

1
2
3
4
5
6
7
8
9
10
11
12
server:
port: 7001

eureka:
instance:
hostname: eureka7001.com #eureka服务端的实例名字
client:
register-with-eureka: false #表识不向注册中心注册自己
fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
service-url:
#设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
1
2
3
4
5
6
7
8
9
10
11
12
13
server:
port: 7002

eureka:
instance:
hostname: eureka7002.com #eureka服务端的实例名字
client:
register-with-eureka: false #表识不向注册中心注册自己
fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
service-url:
#设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7003.com:7003/eureka/

1
2
3
4
5
6
7
8
9
10
11
12
server:
port: 7003

eureka:
instance:
hostname: eureka7003.com #eureka服务端的实例名字
client:
register-with-eureka: false #表识不向注册中心注册自己
fetch-registry: false #表示自己就是注册中心,职责是维护服务实例,并不需要去检索服务
service-url:
#设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7001.com:7001/eureka/
  • Ps: Eureka集群容易理解的一句话就是:你中有我,我中有你
  • 之后启动服务自行测试
  • 当有服务需要注册到eureka的时候,注意defaultZone的编写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
server:
port: 8001

mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package: com.jiatp.springcloud.entity # 扫描此包下的entity ->所有entity别名类所在包
mapper-locations:
- classpath:mybatis/mapper/**/*.xml # mapper映射文件

spring:
application:
name: cloud-client8001 # 很重要,对外暴露的微服务名字
eureka:
client: # 客户端注册进eureka服务列表内
serviceUrl:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

Ribbon负载均衡服务调用

Ribbon主要完成的事情就是负载均衡+RestTemplate调用
Ribbon核心组件IRule策略

  • com.netflix.loadbalancer.RoundRobinRule 轮询
  • com.netflix.loadbalancer.RandomRule 随机
  • com.netflix.loadbalancer.RetryRule 先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定的时间内进行重试;
  • WeightedResponseTimeRule 对RoundRobin的扩展,响应速度越快的实例选择权重越大,越容易被选择;
  • BestAvailableRule会先过滤掉由于多次访问故障处于断路器跳闸状态的服务,然后选择一个并发量小的服务;
  • AvailabilityFilteringRule先过滤故障实例,再选择并发比较小的实例;
  • ZoneAvoidanceRule默认规则,复合判断server所在区域的性能和server的可用性选择服务器;

OpenFeign的使用

导入Maven依赖

1
2
3
4
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

编写配置类

1
2
3
4
5
6
7
@Configuration
public class FeigConfig {
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
}

编写yml文件

1
2
3
4
5
# OpenFeign中的日志监控
logging:
level:
# feign日志以什么级别监控哪个接口
com.jiushiboy.springcloud.service.PaymentFeignService: debug

Hystrix的使用

服务降级

  • 一般用于客户端
  • 首先添加yml文件
1
2
3
4
5
# 服务降级 fallback   服务熔断breaker  服务限流fllowLimit
# 开启feign的hystrix支持,默认是false
feign:
hystrix:
enabled: true
  • 在主启动类上加上@EnableHystrix注解
  • 在需要处理的方法上面加上@HystrixCommand注解,并且编写兜底方法,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#@HystrixCommand注解中fallbackMethod 指定当前方法如果超时或者出现异常去调用哪个方法,commandProperties表示配置触发兜底方法的配置;
@GetMapping("/consumer/payment/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000") //3秒钟以代表正常
})
public String orderTimeOut(@PathVariable("id") Integer id){
String result = orderHystrixService.paymentInfo_TimeOut(id);
log.info(result);
return result;
}

//兜底方法
public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id){
return "我是兜底方法,服务调用超时或出错,请十秒后再试";
}
  • 关于全局配置默认的服务降级,直接上代码
1
2
3
4
5
6
7
8
9
# @DefaultProperties注解标注在类上面,注定默认的fallback方法
@DefaultProperties(defaultFallback = "paymentGlobalFallBackMethod")

# 哪个方法需要默认配置只需要在方法上标注@HystrixCommand

//全局 兜底方法 Global fallback方法
public String paymentGlobalFallBackMethod(){
return "Global异常信息处理,请稍后再试!";
}
  • 这个代码不适合小白观看,得学过才能看懂,毕竟你要是启动服务访问服务都不会,复制了代码也没用,而且也需要使用到OpenFeign;
  • 还有一个问题如果客户端访问的服务宕机了如何给客户端提供保护和降级,直接上代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallBackServiceImpl.class)
public interface PaymentHystrixService {


@GetMapping("/payment/hystrix/ok/{id}")
public String paymentInfo_OK(@PathVariable("id") Integer id);

@GetMapping("/payment/hystrix/timeout/{id}")
public String paymentInfo_TimeOut(@PathVariable("id") Integer id);

}


@Component
public class PaymentFallBackServiceImpl implements PaymentHystrixService {

@Override
public String paymentInfo_OK(Integer id) {
return "---------PaymentFallBackServiceImpl fall back paymentInfo_OK";
}

@Override
public String paymentInfo_TimeOut(Integer id) {
return "---------PaymentFallBackServiceImpl fall back paymentInfo_TimeOut";
}
}

服务熔断:简单来说熔断机制是对应雪崩效应的一种微服务链路保护机制。在SpringCloud框架中,熔断机制是通过Hystrix实现的,Hystrix会监控微服务间的调用状况,当失败的调用到一定的阈值,缺省是五秒内20次调用失败,就会启动熔断机制,熔断机制的注解是@HystrixCommand,下面上代码;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@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 不能负数,请稍候再试,(┬_┬)/~~ id: " +id;
}

/**
涉及到断路器的三个重要参数:快照时间窗,请求总数阈值,错误百分比阈值;
1.快照时间窗(sleepWindowInMilliseconds):断路器确定是否打开需要统计一些请求和错误数据,而统计的时间范围就是快照时间窗,默认为最近的10秒钟;
2.请求总数阈值(requestVolumeThreshold):在快照时间窗内,必须满足请求总阈值才有资格熔断;默认是20,也就是说在10秒内,如果该hystrix命令调用次数不足20次,即使所有的请求都超时或者其他原因失败了,断路器也不会打开;
3.错误百分比阈值(errorThresholdPercentage):当请求总数在快照时间窗内超过了阈值,比如调用了30次,有15次发生了超时异常,也就超过了50%的错误百分比,在默认设定50%阈值情况下,这时候将打开断路器;
/**

服务限流暂时没有,后面会与sentinel的服务限流;
HystrixDashBoard服务监控

  • 导入Maven依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<dependencies>
<!--新增hystrix dashboard-->
<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>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
  • 启动类上的注解
1
2

@EnableHystrixDashboard
  • 如果遇到错误
1
2
3
4
5
6
7
8
9
10
//如果你要监控的服务监控时发生Unable to connect to Command Metric Stream 404时,在需要被监控的服务启动类加入以下代码:
@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;
}

Gateway网关

yml方式玩法

  • 导入Maven
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<dependencies>
<!--新增gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.jiushiboy.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
  • 配置yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的动态路由地址
predicates:
- Path=/payment/get*/** #断言,路径相匹配的进行路由

- id: payment_routh2
#uri: http://localhost:8001
uri: lb://cloud-payment-service #匹配后提供服务的动态路由地址
predicates:
- Path=/payment/getAll/** #断言,路径相匹配的进行路由

eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://localhost:7001/eureka
  • 编写主启动类
1
2
3
4
5
6
7
@SpringBootApplication
@EnableEurekaClient
public class GatewayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GatewayMain9527.class,args);
}
}
  • 断言中还能添加很多种规则,自行百度;

使用java编码方式,代码如下:

1
2
3
4
5
6
7
8
9
@Configuration
public class CatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder) {
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
routes.route("path_rote_jiushiboy", r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
}

Gateway中的自定义filter,yml文件中可选请自行百度;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
首先自定义Gateway网关使用自定义filter需要实现GlobalFilter,Ordered两个接口
Ordered接口主要作用是加载过滤器的顺序,数字越小加载越靠前;
**/
@Configuration
@Slf4j
public class MyLogGatewayFilter implements GlobalFilter, Ordered {


@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("**********************come in MyLogGatewayFilter:"+new Date());
String uname = exchange.getRequest().getQueryParams().getFirst("uname");
if(null==uname){
log.info("用户名为null,非法用户---------");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}

@Override
public int getOrder() {
return 0;
}
}

Config配置

首先搭建服务端

  • 需要在Github中新建一个仓库,我这里新建仓库为Springcloud-config
  • pom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.jiushiboy.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</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>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
  • application.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server:
port: 3344
spring:
application:
name: cloud-config-center
cloud:
config:
server:
git:
uri: https://github.com/jiushiboy/springcloud-config.git
search-paths: # 文件目录
- springcloud-config
label: master # 分支
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
  • 启动类
1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableConfigServer
public class MainAppConfigCenter3344 {

public static void main(String[] args) {
SpringApplication.run(MainAppConfigCenter3344.class, args);
}

}

——-至此Config服务端搭建完毕———
Config客户端开始

  • pom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.jiushiboy.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</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>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
  • 客户端bootstrap.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server:
port: 3355

spring:
application:
name: config-client
cloud:
#config客户端配置
config:
label: master #分支名称
name: config #配置文件名称
profile: dev #读取后缀名称
uri: http://localhost:3344 #服务端接口路径
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka
#暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
  • 主启动类
1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3355 {

public static void main(String[] args) {
SpringApplication.run(ConfigClientMain3355.class, args);
}

}
  • Controller层代码
1
2
3
4
5
6
7
8
9
10
@RestController
@RefreshScope //注解用来刷新服务端配置是否发生变化
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo(){
return configInfo;
}
}
  • 当你修改了Github上面的配置文件,服务端读取到实时更新的,但是客户端却没有,则需要加上@RefreshScope,并且需要运维人员执行命令,因为客户端在我本地我用的cmd命令执行的:
1
curl -X POST "http://localhost:3355/actuator/refresh"
  • 但是如果我们Config客户端很多的情况下,如何通知多服务呢? Bus总线!

Bus总线

服务端搭建

  • pom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.jiushiboy.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</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>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
  • application.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
server:
port: 3344
spring:
application:
name: cloud-config-center
cloud:
config:
server:
git:
uri: https://github.com/jiushiboy/springcloud-config.git
search-paths:
- springcloud-config
label: master
#配置rabbitmq
rabbitmq:
host: localhost # ip
port: 5672 # 端口号
username: guest # 账号
password: guest # 密码

eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka

#rabbitmq相关配置,暴露Bus刷新配置的端点
management:
endpoints: #暴露Bus刷新配置的端点
web:
exposure:
include: 'bus-refresh'
  • 服务端启动类
1
2
3
4
5
6
7
8
9
@SpringBootApplication
@EnableConfigServer
public class MainAppConfigCenter3344 {

public static void main(String[] args) {
SpringApplication.run(MainAppConfigCenter3344.class, args);
}

}

测试端搭建

  • pom
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.jiushiboy.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</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>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
  • bootstrap.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
server:
port: 3366

spring:
application:
name: config-client
cloud:
#Config 客户端配置
config:
label: master #分支名字
name: config #配置文件名昌
profile: dev #读取后缀
uri: http://localhost:3344 #配置中心地址
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
#服务注册到Eureka
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka
#暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
  • 启动类
1
2
3
4
5
6
7
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3366 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientMain3366.class, args);
}
}
  • 控制层
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@RefreshScope
@RestController
public class ConfigClientController {
@Value("${server.port}")
private String serverPort;

@Value("${config.info}")
private String configInfo;

@GetMapping("/configInfo")
public String getConfigInfo(){
return configInfo+"----------------"+serverPort;
}
}

通过rabbitMq达到广播效果,实时同步github中的config
SpringCloud Bus动态刷新全局广播执行命令(也就是通知全部的bus客户端刷新)

1
curl -X POST "http://localhost:3344/actuator/bus-refresh"

SpringCloud Bus动态刷新定点通知(指定客户端刷新通知,简单地说就是精确打击)

1
curl -X POST "http://localhost:3344/actuator/bus-refresh/客户端名称如config-client3366"

Stream消息驱动

当使用SpringCloud时,需要同时用到RabbitMQ和Kafka时,使用Stream消息驱动并不需要你同时掌握这两个技术,只需要借助Stream即可完成;

  • 这次就不复制代码了,代码github路径https://github.com/jiushiboy/springcloud
  • 分别拉取三个服务:cloud-stream-rabbitmq-provider8801、cloud-stream-rabbitmq-consumer8802、cloud-stream-rabbitmq-consumer8803三个模块
  • 如何解决重复消费:将两个服务分到一个group组,在配置文件种配置就行;
  • 如何解决消息丢失,当然也是group分组;生产者发送信息,消费者A停止服务了,但是重启服务之后也会重新读取信息;

Sleuth分布式请求链路跟踪

第一步下载jar

1
https://dl.bintray.com/openzipkin/maven/io/zipkin/java/zipkin-server/

Windows直接在cmd命令java -jar zipk.xxxx 运行jar
在需要用到sleuth的模块中引入Maven(这里演示的是cloud-provider-payment8001、cloud-consumer-order80、cloud-server-eureka7001)

1
2
3
4
5
<!--包含了sleuth+zipkin-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

在yml文件中添加配置

1
2
3
4
5
6
7
8
spring:
application:
name: cloud-payment-service
zipkin:
base-url: http://localhost:9411/
sleuth:
sampler:
probability: 1