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

eureka客户端连接到eureka server并维持心跳;
这样维护人员就可以通过server来监控系统中各个client是否正常运行;
如何实现服务注册:
1、引入eureka client依赖;
2、配置yml文件
3、主启动类添加注解
eureka集群原理:互相注册,相互守望
自我保护机制(AP模型)
某个时刻某一个微服务不可用了,Eureka不会立即清理,依旧会对该微服务的信息进行保存;
Ribbon
负载均衡 + restTemplate调用
nginx 和 ribbon 的区别?
nginx服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现请求转发;即负载均衡是由服务端实现
ribbon本地负载均衡,在调用微服务接口时,会在注册中心上获取注册信息服务列表之后缓存到JVM本地,
从而在本地实现RPC远程服务调用;
public static final String PAYMENT_URL = "http://CLOUD-PAYMENT-SERVICE";restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
工作原理
负载均衡轮询算法:(CAS实现)
rest接口请求次数 % 服务器集群总数量 = 实际调用服务器位置下标 ;
每次服务重启后rest接口计数从1开始;
OpenFeign
1、引入openFeign的依赖 2、主启动类开启feign功能:@EnableFeignClients
3、编写接口 添加注解;@component 、 @FeignClient(value = “CLOUD-PAYMENT-SERVICE”)
类似于我们后端程序员的面向接口开发的形式;
@Component@FeignClient(value = "CLOUD-PAYMENT-SERVICE")public interface PaymentFeignService {@GetMapping("/payment/get/{id}")CommonResult<Payment> getPaymentById(@PathVariable("id") Long id);}
Hystrix
服务降级:服务器忙,请稍后再试,并立刻返回一个友好提示;fallback
服务熔断:类比保险丝达到最大服务访问后,直接拒绝访问,拉闸限电,然后调用服务降级方法并返回友好提示
服务限流:秒杀高并发等操作,严禁一窝蜂拥挤过来,大家排队,一秒钟N个,有序进行;
服务降级
服务超时或直接出错后调用fallback 提供者端配置hystrix
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000") //服务最多运行3秒})public String paymentInfo_TimeOut(Integer id){int timeNumber = 5;try {TimeUnit.SECONDS.sleep(timeNumber);} catch (InterruptedException e) {e.printStackTrace();}// int age = 10 / 0 ;return "线程池: " + Thread.currentThread().getName() + "系统繁忙,请稍后再试, id: " + id + "\t" + "耗时(s)" + timeNumber;}public String paymentInfo_TimeOutHandler(Integer id){return "线程池: " + Thread.currentThread().getName() + "系统繁忙,请稍后再试, id: " + id + "\t" + "┭┮﹏┭┮";}
消费者端:(hystrix建议使用在消费者端)
@GetMapping("/consumer/payment/hystrix/timeout/{id}")@HystrixCommand(fallbackMethod = "paymentTimeoutFallbackMethod", commandProperties = {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "1500")})public String paymentInfo_TimeOut(@PathVariable("id") Integer id){return paymentHystrixService.paymentInfo_TimeOut(id);}public String paymentTimeoutFallbackMethod(@PathVariable("id")Integer id){return "我是消费者80,对方支付系统繁忙请10秒中之后再试,或者请检查一下自己,┭┮﹏┭┮";}
当兜底方法和业务逻辑混合在一起时,代码量耦合度很高;需要配置全局fallback;
@Slf4j@RestController@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")public class OrderHystrixController {@HystrixCommand //不配置具体的fallbackMethod就走全局的fallbackpublic String paymentInfo_TimeOut(@PathVariable("id") Integer id){return paymentHystrixService.paymentInfo_TimeOut(id);}//下面是全局fallback方法public String payment_Global_FallbackMethod(){return "Global异常处理信息,请稍后再试,/(ㄒoㄒ)/~~";}}
将业务逻辑和降级处理方法分离; 服务降级放在消费者端
@Component@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentFallBackService.class)public interface PaymentHystrixService {@GetMapping("/payment/hystrix/ok/{id}")String paymentInfo_OK(@PathVariable("id") Integer id);@GetMapping("/payment/hystrix/timeout/{id}")String paymentInfo_TimeOut(@PathVariable("id") Integer id);}
@Componentpublic class PaymentFallBackService implements PaymentHystrixService{@Overridepublic String paymentInfo_OK(Integer id) {return "-------PaymentFallBackService fall back _OK,┭┮﹏┭┮";}@Overridepublic String paymentInfo_TimeOut(Integer id) {return "-------PaymentFallBackService fall _TimeOut,┭┮﹏┭┮";}}
什么情况下会导致服务降级?
答:程序本身出现出错误 int age = 10 / 0;
远程调用服务提供者超时;
服务提供者宕机;
服务熔断
| name | value |
|---|---|
| circuitBreaker.enabled | 是否开始断路器 |
| circuitBreaker.requestVolumeThreshold | 请求次数 |
| ircuitBreaker.sleepWindowInMilliseconds | 时间窗口期 |
| circuitBreaker.errorThresholdPercentage | 失败率达到多少后跳闸 |
@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;}
熔断类型
熔断打开:请求不再调用当前服务
熔断关闭:熔断关闭不会对服务进行熔断
熔断半开:部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断
Gateway

三大核心概念:
路由(route)、 断言(predicate)、 过滤(filter)
yml配置:
server:port: 9527spring:application:name: cloud-gatewaycloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由routes:- id: payment_routh #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001 #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/get/** # 断言,路径相匹配的进行路由- id: payment_routh2 #payment_route #路由的ID,没有固定规则但要求唯一,建议配合服务名#uri: http://localhost:8001 #匹配后提供服务的路由地址uri: lb://cloud-payment-service #匹配后提供服务的路由地址predicates:- Path=/payment/lb/** # 断言,路径相匹配的进行路由#- After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]#- Cookie=username,zzyy#- Header=X-Request-Id, \d+ #请求头要有X-Request-Id属性并且值为整数的正则表达式
断言类型:
自定义全局GlobalFilter
@Slf4j@Componentpublic class MyLogGatewayFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("********come in global filter" + new Date());String uname = exchange.getRequest().getQueryParams().getFirst("uname");if(uname == null){log.info("*****用户名为null,非法用户,┭┮﹏┭┮");exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);return exchange.getResponse().setComplete();}return chain.filter(exchange);}@Overridepublic int getOrder() {return 0;}}
Config
springcloud config 为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。
springcloud config分为服务端和客户端;
server端 yml:
server:port: 3344spring:application:name: cloud-config-centercloud:config:server:git:uri: git@github.com:Stefan-zhc/cloud-config.gitsearch-paths: ## 搜索目录- cloud-config##读取分支label: maineureka:client:service-url:defaultZone: http://localhost:7001/eureka
服务端主启动类:@EnableConfigServer
bootstrap.yml是系统级的,优先级更高;
client端 yml:
server:port: 3355spring:application:name: config-clientcloud:config:label: main #分支名称name: config #配置文件名称profile: prod #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.ymluri: http://localhost:3344 #config server地址eureka:client:service-url:defaultZone: http://localhost:7001/eureka/#暴露监控端点management:endpoints:web:exposure: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"
