SpringCloud快速入门
Eureka注册中心
1、服务端
添加服务端pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
设置application.xml
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com #服务端实例名称
client:
register-with-eureka: false #不注册自己
fetch-registry: false #自己是注册中心 维护服务实例 不检索服务
service-url:
defaultZone: http://localhost:7001/eureka/
# server:
# enable-self-preservation: false #自我保护关闭
服务端开启注解
@EnableEurekaServer //开启服务中心注解
@SpringBootApplication
public class EurekaServerMain {
public static void main(String[] args) {
SpringApplication.run(EurekaServerMain.class, args);
}
}
2、客户端
添加客户端pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
设置application.xml
server:
port: 80
spring:
application: #注册名
name: order
eureka:
client:
register-with-eureka: true #注册自己 默认为true
fetch-registry: true #是否从eureka抓取自己注册信息,默认为true,集群必须为true才能配合Ribbon使用负载均衡
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
instance: #实例名
hostname: Order-Service
客户端开启注解
@SpringBootApplication
@EnableEurekaClient
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
}
3.集群注册中心
server:
port: 7002
eureka:
instance:
hostname: eureka7002.com #服务端实例名称
client:
register-with-eureka: false #不注册自己
fetch-registry: false #自己是注册中心 维护服务实例 不检索服务
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
server:
port: 7001
eureka:
instance:
hostname: eureka7002.com #服务端实例名称
client:
register-with-eureka: false #不注册自己
fetch-registry: false #自己是注册中心 维护服务实例 不检索服务
service-url:
defaultZone: http://eureka7002.com:7002/eureka/
配置文件中设置相互守望7002注册到7001,7001注册到7002
客户端注册到集群上
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/db2019?useSSL=false&serverTimezone=GMT&allowPublicKeyRetrieval=True
username: root
password: 123456
mybatis:
mapper-locations: classpath:mapper/*.xml #配置Mybatis的Mapper文件夹路径
type-aliases-package: com.zuoxiaozi.springcloud.entities #所有entity别名类所在包
eureka:
client:
register-with-eureka: true #注册自己 默认为true
fetch-registry: true #是否从eureka抓取自己注册信息,默认为true,集群必须为true才能配合Ribbon使用负载均衡
service-url:
defaultZone: http://localhost:7001/eureka/ ,http://eureka7002.com:7002/eureka/
instance:
instance-id: Payment-8001
prefer-ip-address: true #访问路径可以显示ip
Ribbon负载均衡
可以导入Ribbon依赖,Openfeign集成Ribbon,默认为轮询,application.yml配置负载均衡,在 “1” 调用 “多” 的 “1” 中配置针对 ”多“ 的服务名进行配置负载均衡,实现负载均衡效果;
默认是轮询,底层原理:访问次数%服务个数=调用服务id数
usersevice: #需要访问的服务名称 在服务的application.yml中对应
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #负载均衡规则 针对单独服务提供
#userservice: #服务的服务名称 在服务的application.yml中对应
# ribbon:
# NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule #针对单独服务提供
ribbon:
eager-load:
enabled: true #开启饥饿加载
clients: userservice #指定饥饿加载的服务名称 多个换行: -userservice -service2
Openfeign远程调用
1、客户端添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2、客户端建接口
使用注册@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE") /*指定调用的服务,注册在eureka中的名称/application.yml中配置的name*/
public interface PaymentFeignService {
@GetMapping(value = "/payment/get/{id}") /*远程调用的服务中的Controller*/
public CommonResult getPaymentById(@PathVariable("id") Long id);
}
3、客户端编写自己的Controller类
@RestController
@Slf4j
public class OrderFeignController {
@Resource
private PaymentFeignService paymentFeignService;
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id) {
return paymentFeignService.getPaymentById(id); /*调用定义的服务接口*/
}
}
4、客户端启动类开启注解
@SpringBootApplication
@EnableFeignClients /*开启feign*/
public class FeignMainOrder80 {
public static void main(String[] args) {
SpringApplication.run(FeignMainOrder80.class, args);
}
}
Gateway网关
1、添加pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
2、设置application.xml
注册到eureka注册中心
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh #payment_routh #路由的ID,没有固定规则但要求唯一,简易配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-provider-hystrix-payment #匹配后提供服务的路由地址 lb就是负载均衡
predicates:
- Path=/payment/hystrix/ok/** #断言,路径相匹配的进行路由
- id: payment_routh2 #payment_routh #路由的ID,没有固定规则但要求唯一,简易配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-provider-hystrix-payment #匹配后提供服务的路由地址
predicates:
- Path=/payment/hystrix/timeout/** #断言,路径相匹配的进行路由
#- After=2021-11-08T12:35:07.412+08:00[GMT+08:00]
#- Cookie=username,zzyy
#- Header=X-Request-Id, \d+ #请求头要有X-Request-Id属性并且值为整数的正则表达式
#- Host=**.atguigu.com
#- Method=GET
#- Query=username, \d+ #要有参数名username并且值还要啥整数才能路由
eureka:
instance:
hostname: cloud-gateway-service
client:
register-with-eureka: true
fetch-registry: true
service-url:
defaultZone: http://localhost:7001/eureka
3、自定义Filter过滤器
路由过滤器、defaultFilter、 全局过滤器的执行顺序?
- order值越小, 优先级越高
- 当order值一 样时,顺序是defaultFilter最先,然后是局部的路由过滤器,最后是全局过滤器
@Component /*注册到spring容器中*/
@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");//每次进来后判断带不带uname这个key
if(uname == null){
log.info("*********用户名为null ,非法用户,o(╥﹏╥)o");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); //uname为null非法用户
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0; //设置过滤器的优先级
}
}
Hystrix断路器
可在服务端,也可以在客户端
添加pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
1、服务端
设置application.xml
server:
port: 8001
spring:
application:
name: cloud-provider-hystrix-payment
eureka:
client:
fetch-registry: true
register-with-eureka: true
service-url:
defaultZone: http://localhost:7001/eureka/
启动类开启注解
@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker /*开启hystrix断路器配置*/
public class FeignHystrixOrder80Main {
public static void main(String[] args) {
SpringApplication.run(FeignHystrixOrder80Main.class, args);
}
}
Service服务熔断Fallback(兜底)方法
@Service
public class PaymentService {
/**
* 正常访问
* @param id
* @return
*/
public String paymentInfo_OK(Integer id) {
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_OK,id:"
+ id + "\t" + "√";
}
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
}) /*配置fallback*/
public String paymentInfo_TimeOut(Integer id) {
int timeNumber = 3;
//int age = 10 / 0;
try {
TimeUnit.SECONDS.sleep(timeNumber);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_TimeOut,id: "
+ id + "\t" + "√" + " 耗时" + timeNumber + "s";
}
public String paymentInfo_TimeOutHandler(Integer id) {
return "线程池:" + Thread.currentThread().getName() + "paymentInfo_TimeOut,id: "
+ id + "\t" + " 系统繁忙";
}
/*==============服务熔断=====================*/
@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;
}
}
Controller中调用paymentCircuitBreaker()方法
@RestController
@Slf4j
public class PaymentController {
@Autowired
private PaymentService paymentService;
@Value("${server.port}")
private String serverPort;
@GetMapping("/payment/hystrix/ok/{id}")
private String paymentInfo_OK(@PathVariable("id") Integer id) {
String result = paymentService.paymentInfo_OK(id);
log.info("*********:" + result);
return result;
}
@GetMapping("/payment/hystrix/timeout/{id}")
private String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
String result = paymentService.paymentInfo_TimeOut(id);
log.info("*********:" + result);
return result;
}
/*===============服务熔断==============*/
@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id){
String result = paymentService.paymentCircuitBreaker(id); //调用断路器方法
log.info("*******result:"+result);
return result;
}
}
2、客户端
设置application.xml
server:
port: 80
spring:
application:
name: cloud-consumer-feign-hystrix-order80
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/
fetch-registry: true
register-with-eureka: true
feign:
hystrix:
enabled: true #设置 对熔断降级的支持 如果处理自身的容错就开启。开启方式与生产端不一样。
client:
config:
default:
connectTimeout: 300000 #设置feign请求超时时间 解决Read timed out问题
readTimeout: 300000
启动类开启注解
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrix /*开启hystrix*/
@EnableCircuitBreaker /*开启hystrix断路器配置*/
public class FeignHystrixOrder80Main {
public static void main(String[] args) {
SpringApplication.run(FeignHystrixOrder80Main.class, args);
}
}
PaymentFallbackService实现接口PaymentHystrixService做为全局降级类
Feign接口注解上指定fallback类
@Component
@FeignClient(value = "cloud-provider-hystrix-payment", fallback = PaymentFallbackService.class) /*指定调用的服务名称 和 服务接口,指定fallback类*/
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);
}
降级类PaymentFallbackService
@Component
public class PaymentFallbackService implements PaymentHystrixService { //实现feign远程调用接口
@Override
public String paymentInfo_OK(Integer id) {
return "PaymentFallbackService, fall back_paymentInfo_OK,505";
}
@Override
public String paymentInfo_TimeOut(Integer id) {
return "PaymentFallbackService, fall back_paymentInfo_TimeOut,505";
}
}
Controller中正常方法
@RestController
@Slf4j
public class OrderHystrixController {
@Autowired
private PaymentHystrixService paymentHystrixService;
@GetMapping("/consumer/feign/hystrix/order/ok/{id}")
public String payment_InfoOK(@PathVariable("id") Integer id) {
return paymentHystrixService.paymentInfo_OK(id);
}
@HystrixCommand /*启用fallback注解*/
@GetMapping("/consumer/feign/hystrix/order/timeout/{id}")
public String payment_InfoTime(@PathVariable("id") Integer id) {
//int age = 10 / 0;
return paymentHystrixService.paymentInfo_TimeOut(id);
}
}