源码
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
主启动
业务类
第一步: 将依赖引入到需要热部署子模块的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的使用
服务降级
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; }
|
服务限流暂时没有,后面会与sentinel的服务限流;
HystrixDashBoard服务监控
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方式玩法
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>
|
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>
|
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客户端开始
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>
|
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); }
}
|
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总线
服务端搭建
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>
|
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); }
}
|
测试端搭建
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>
|
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
|