1、建module 2、改pom
3、写yml 4、主启动 5、业务类

Eureka

image-20220606203254744.png

eureka客户端连接到eureka server并维持心跳;
这样维护人员就可以通过server来监控系统中各个client是否正常运行;


如何实现服务注册:

1、引入eureka client依赖;
2、配置yml文件
3、主启动类添加注解


eureka集群原理:互相注册,相互守望
image-20220607164822318.png

自我保护机制(AP模型)

某个时刻某一个微服务不可用了,Eureka不会立即清理,依旧会对该微服务的信息进行保存;
image-20220607165118391.png

Ribbon

负载均衡 + restTemplate调用

nginx 和 ribbon 的区别?

nginx服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现请求转发;即负载均衡是由服务端实现
ribbon本地负载均衡,在调用微服务接口时,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,
从而在本地实现RPC远程服务调用;

  1. public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";
  2. restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);

工作原理
image-20220607210618568.png

负载均衡轮询算法:(CAS实现)

rest接口请求次数 % 服务器集群总数量 = 实际调用服务器位置下标 ;
每次服务重启后rest接口计数从1开始;

OpenFeign

1、引入openFeign的依赖 2、主启动类开启feign功能:@EnableFeignClients
3、编写接口 添加注解;@component @FeignClient(value = “CLOUD-PAYMENT-SERVICE”)

类似于我们后端程序员的面向接口开发的形式;

  1. @Component
  2. @FeignClient(value = "CLOUD-PAYMENT-SERVICE")
  3. public interface PaymentFeignService {
  4. @GetMapping("/payment/get/{id}")
  5. CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);
  6. }

Hystrix

服务降级:服务器忙,请稍后再试,并立刻返回一个友好提示;fallback
服务熔断:类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级方法并返回友好提示
服务限流:秒杀高并发等操作,严禁一窝蜂拥挤过来,大家排队,一秒钟N个,有序进行;

服务降级

服务超时或直接出错后调用fallback 提供者端配置hystrix

  1. @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
  2. @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000") //服务最多运行3秒
  3. })
  4. public String paymentInfo_TimeOut(Integer id){
  5. int timeNumber = 5;
  6. try {
  7. TimeUnit.SECONDS.sleep(timeNumber);
  8. } catch (InterruptedException e) {
  9. e.printStackTrace();
  10. }
  11. // int age = 10 / 0 ;
  12. return "线程池: " + Thread.currentThread().getName() + "系统繁忙,请稍后再试, id: " + id + "\t" + "耗时(s)" + timeNumber;
  13. }
  14. public String paymentInfo_TimeOutHandler(Integer id){
  15. return "线程池: " + Thread.currentThread().getName() + "系统繁忙,请稍后再试, id: " + id + "\t" + "┭┮﹏┭┮";
  16. }

消费者端:(hystrix建议使用在消费者端)

  1. @GetMapping("/consumer/payment/hystrix/timeout/{id}")
  2. @HystrixCommand(fallbackMethod = "paymentTimeoutFallbackMethod", commandProperties = {
  3. @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds"
  4. ,value = "1500")
  5. })
  6. public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
  7. return paymentHystrixService.paymentInfo_TimeOut(id);
  8. }
  9. public String paymentTimeoutFallbackMethod(@PathVariable("id")Integer id){
  10. return "我是消费者80,对方支付系统繁忙请10秒中之后再试,或者请检查一下自己,┭┮﹏┭┮";
  11. }

当兜底方法和业务逻辑混合在一起时,代码量耦合度很高;需要配置全局fallback;

  1. @Slf4j
  2. @RestController
  3. @DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
  4. public class OrderHystrixController {
  5. @HystrixCommand //不配置具体的fallbackMethod就走全局的fallback
  6. public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
  7. return paymentHystrixService.paymentInfo_TimeOut(id);
  8. }
  9. //下面是全局fallback方法
  10. public String payment_Global_FallbackMethod()
  11. {
  12. return "Global异常处理信息,请稍后再试,/(ㄒoㄒ)/~~";
  13. }
  14. }

将业务逻辑和降级处理方法分离; 服务降级放在消费者端

  1. @Component
  2. @FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentFallBackService.class)
  3. public interface PaymentHystrixService {
  4. @GetMapping("/payment/hystrix/ok/{id}")
  5. String paymentInfo_OK(@PathVariable("id") Integer id);
  6. @GetMapping("/payment/hystrix/timeout/{id}")
  7. String paymentInfo_TimeOut(@PathVariable("id") Integer id);
  8. }
  1. @Component
  2. public class PaymentFallBackService implements PaymentHystrixService{
  3. @Override
  4. public String paymentInfo_OK(Integer id) {
  5. return "-------PaymentFallBackService fall back _OK,┭┮﹏┭┮";
  6. }
  7. @Override
  8. public String paymentInfo_TimeOut(Integer id) {
  9. return "-------PaymentFallBackService fall _TimeOut,┭┮﹏┭┮";
  10. }
  11. }

什么情况下会导致服务降级?

答:程序本身出现出错误 int age = 10 / 0;
远程调用服务提供者超时;
服务提供者宕机;


服务熔断

name value
circuitBreaker.enabled 是否开始断路器
circuitBreaker.requestVolumeThreshold 请求次数
ircuitBreaker.sleepWindowInMilliseconds 时间窗口期
circuitBreaker.errorThresholdPercentage 失败率达到多少后跳闸
  1. @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = {
  2. @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否开启断路器
  3. @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 请求次数
  4. @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 时间窗口期
  5. @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失败率达到多少后跳闸
  6. })
  7. public String paymentCircuitBreaker(@PathVariable("id") Integer id){
  8. if(id < 0){
  9. throw new RuntimeException("*******id 不能为负数");
  10. }
  11. String serialNumber = IdUtil.simpleUUID();
  12. return Thread.currentThread().getName() + "\t" + "调用成功,流水号:" + serialNumber;
  13. }
  14. public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){
  15. return "id 不能为负数,请稍后再试,┭┮﹏┭┮ id :" + id;
  16. }

熔断类型
熔断打开:请求不再调用当前服务
熔断关闭:熔断关闭不会对服务进行熔断
熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断

Gateway

image-20220611160143714.png

三大核心概念:
路由(route)、 断言(predicate)、 过滤(filter)

yml配置:

  1. server:
  2. port: 9527
  3. spring:
  4. application:
  5. name: cloud-gateway
  6. cloud:
  7. gateway:
  8. discovery:
  9. locator:
  10. enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
  11. routes:
  12. - id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
  13. #uri: http://localhost:8001 #匹配后提供服务的路由地址
  14. uri: lb://cloud-payment-service #匹配后提供服务的路由地址
  15. predicates:
  16. - Path=/payment/get/** # 断言,路径相匹配的进行路由
  17. - id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名
  18. #uri: http://localhost:8001 #匹配后提供服务的路由地址
  19. uri: lb://cloud-payment-service #匹配后提供服务的路由地址
  20. predicates:
  21. - Path=/payment/lb/** # 断言,路径相匹配的进行路由
  22. #- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
  23. #- Cookie=username,zzyy
  24. #- Header=X-Request-Id, \d+ #请求头要有X-Request-Id属性并且值为整数的正则表达式

断言类型:
image-20220611195021515.png

自定义全局GlobalFilter

  1. @Slf4j
  2. @Component
  3. public class MyLogGatewayFilter implements GlobalFilter, Ordered {
  4. @Override
  5. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  6. log.info("********come in global filter" + new Date());
  7. String uname = exchange.getRequest().getQueryParams().getFirst("uname");
  8. if(uname == null){
  9. log.info("*****用户名为null,非法用户,┭┮﹏┭┮");
  10. exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
  11. return exchange.getResponse().setComplete();
  12. }
  13. return chain.filter(exchange);
  14. }
  15. @Override
  16. public int getOrder() {
  17. return 0;
  18. }
  19. }

Config

springcloud config 为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。
image-20220613142436314.png

springcloud config分为服务端和客户端;

server端 yml:

  1. server:
  2. port: 3344
  3. spring:
  4. application:
  5. name: cloud-config-center
  6. cloud:
  7. config:
  8. server:
  9. git:
  10. uri: git@github.com:Stefan-zhc/cloud-config.git
  11. search-paths: ## 搜索目录
  12. - cloud-config
  13. ##读取分支
  14. label: main
  15. eureka:
  16. client:
  17. service-url:
  18. defaultZone: http://localhost:7001/eureka

服务端主启动类:@EnableConfigServer
bootstrap.yml是系统级的,优先级更高;

client端 yml:

  1. server:
  2. port: 3355
  3. spring:
  4. application:
  5. name: config-client
  6. cloud:
  7. config:
  8. label: main #分支名称
  9. name: config #配置文件名称
  10. profile: prod #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
  11. uri: http://localhost:3344 #config server地址
  12. eureka:
  13. client:
  14. service-url:
  15. defaultZone: http://localhost:7001/eureka/
  16. #暴露监控端点
  17. management:
  18. endpoints:
  19. web:
  20. exposure:
  21. include: "*"

客户端controller层:添加@RefreshScope注解


server端3344 直连github,当github中yml文件被修改后,config server3344会直接得到配置文件的更新;
client端3355 连接到server端3344, 当github中yml文件被修改后, client3355不能直接得到最新修改内容;
需要在controller层添加==@RefreshScope注解,配置报端监控端点==;并且发送post请求:
curl -X post http://localhost:3355/actuator/refresh 实现得到github修改的yml文件内容;


Bus

一次通知,到处知道
1、添加依赖 2、配置yml rabbit的host、port、username、password信息

服务端3344 yml:

server:
  port: 3344

spring:
  application:
    name: cloud-config-center
  cloud:
    config:
      server:
        git:
          uri: https://github.com/Stefan-zhc/cloud-config.git
          username: Stefan-zhc
          password: mko1999.
          search-paths:  ## 搜索目录
            - cloud-config
          skip-ssl-validation: true
      ##读取分支
      label: main

rabbitmq:
  host: 192.168.86.128
  port: 5672
  username: stefan
  password: 123456

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


#暴露监控端点
management:
  endpoints:
    web:
      exposure:
        include: "bus-refresh"