SpringCloud搭建保姆级教程

一、搭建服务注册与发现中⼼

使⽤Spring Cloud Netflix 中的 Eureka 搭建服务注册与发现中⼼

1、创建SpringBoot应用添加依赖

1、spring web
2、eureka server

2、配置服务注册与发现中⼼

复制代码
## 设置服务注册与发现中⼼的端⼝
server:
  port: 8761
## 在微服务架构中,服务注册中⼼是通过服务应⽤的名称来区分每个服务的
## 我们在创建每个服务之后,指定当前服务的 应⽤名/项⽬名
spring:
  application: null
  name: service-eureka
eureka:
  client:
    ## ip 就是服务注册中⼼服务器的ip,port 就是服务注册与发现中⼼设置的port
    service-url:
      defaultZone: 'http://192.168.54.59:8761/eureka'
    ## 设置服务注册与发现中⼼是否为为集群搭建(如果为集群模式,多个eureka节点之间需要相互注册)
    register-with-eureka: false
     ## 设置服务注册与发现中是否作为服务进⾏注册
    fetch-registry: false

3、在启动类添加@EnableEurekaServer注解

复制代码
@SpringBootApplication
@EnableEurekaServerpublic class ServiceEurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceEurekaApplication.class, args);
    }
}

4、运⾏及访问

二、服务注册

创建保存订单的服务(order-add)注册到服务注册与发现中⼼

1、创建SpringBoot应⽤

创建spring boot应⽤,完成功能开发

2、注册服务

将能够完成特定业务的SpringBoot应⽤作为服务提供者,注册到服务注册与发现中⼼

2.1、添加依赖eureka-server

复制代码
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

2.2、配置application.yml

复制代码
server:
  port: 9001
## 当前应⽤名会作为服务唯⼀标识注册到eureka
spring:
  application:
    name: order-add
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: 'jdbc:mysql://localhost:3306/db_2010_sc?characterEncoding=utf-8'
    username: root
    password: admin123
mybatis:
  mapper-locations: 'classpath:mappers/*'
  type-aliases-package: com.qfedu.order.beans
## 配置Eureka服务注册与发现中⼼的地址
eureka:
  client: 
      service-url:
        defaultZone: 'http://localhost:8761/eureka'

2.3、在当前服务应⽤的启动类添加 @EnableEurekaClient 注解

复制代码
@SpringBootApplication
@MapperScan("com.qfedu.order.dao")
@**Enab**leEurekaClientpublic class OrderAddApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderAddApplication.class, args);
    }
}

三、服务发现-Ribbon

服务消费者(api-order-add)通过eureka查找服务提供者(order-add),通过服务调⽤组件调⽤提供者

  • eureka server
  • ribbon

1、基础配置

Ribbon客户端已经停更进维啦

1.1、创建SpringBoot应⽤,添加依赖

  • eureka server
  • ribbon

1.2、配置application.yml

复制代码
server:
  port: 8001
spring:
  application: 
    name: api-order-add
eureka:
  client: 
    service-url: 
        defaultZone: 'http://localhost:8761/eureka'

1.3、在启动类添加 @EnableDiscoveryClient注解

复制代码
@SpringBootApplication
@EnableDiscoveryClientpublic class ApiOrderAddApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiOrderAddApplication.class, args);
    }
}

2、服务调⽤

2.1、配置RestTemplate

复制代码
@Configuration
public class AppConfig {
    @LoadBalanced//启⽤Ribbon(负载均衡)
@Beanpublic RestTemplate getRestTemplate(){
        return new RestTemplate();
    }
}

2.2、在Service中注⼊RestTemplate对象调⽤服务

复制代码
@Service
public class OrderAddServiceImpl implements OrderAddService {
    @Autowired
    private RestTemplate restTemplate;
    @Override
    public ResultVO saveOrder(Order order) {
        //1. 调⽤ order-add服务进⾏保存
        ResultVO vo = restTemplate.postForObject("http://order-add/order/add", order, ResultVO.class);
        //2. 调⽤ orderitem-add 保存订单快照
        //3. 调⽤ stock-update 修改商品库存
        //4. 调⽤ shopcart-del 删除购物⻋记录
        return null;
    }
}

3、Ribbon服务调⽤说明

@LoadBalanced注解是Ribbon的⼊⼝,在RestTemplate对象上添加此注解之后,再使
⽤RestTemplate发送REST请求的时候,就可以通过Ribbon根据服务名称从Eureka中查
找服务对应的访问地址列表,再根据负载均衡策略(默认轮询)选择其中的⼀个,然后
完成服务的调⽤

  • 获取服务列表
  • 根据负载均衡策略选择服务
  • 完成服务调⽤

四、基于Ribbon进⾏服务调⽤的参数传递

1、RestTemplate发送调⽤请求的⽅法

SpringCloud的服务调⽤是基于REST的,因此当服务提供者规定了请求的⽅式,服务消
费者必须发送对应⽅式的请求才能完成服务的调⽤,RestTemplate提供了多个⽅法⽤于
发送不同形式的请求。

复制代码
//post⽅式请求
restTemplate.postForObject();
//get⽅式请求
restTemplate.getForObject();
//delete⽅式请求
restTemplate.delete();
//put⽅式请求
restTemplate.put();

2、put/post请求传参

1、服务消费者请求传参

复制代码
//参数1:访问服务的url
//参数2:传递的对象参数
//参数3:指定服务提供者返回的数据类型
ResultVO vo = restTemplate.postForObject("http://order-add/order/add",order, ResultVO.class);

2、服务提供者接收参数

复制代码
@PostMapping("/add")
public ResultVO addOrder(@RequestBody Order order){
   return orderService.saveOrder(order);
}

3、get请求传参

1、服务消费者请求传参

复制代码
String userId = order.getUserId();
ResultVO vo = restTemplate.getForObject("http://order-add/order/add?userId="+userId, ResultVO.class);

2、服务提供者接收参数

复制代码
@GetMapping("/add")
public ResultVO addOrder(Order order){
    return orderService.saveOrder(order);
}
@GetMapping("/add")
public ResultVO addOrder(String userId){
    //return orderService.saveOrder(order);
}

五、服务发现-Feign

1、基础配置

1.1、创建SpringBoot应⽤,添加依赖

spring web
eureka server
OpenFeign

1.2、配置application.yml

复制代码
server:
  port: 8002
spring:
  application:
    name: api-order-add-feign
eureka:
  client:
    service-url:
      defaultZone: 'http://localhost:8761/eureka'

1.3、在启动类添加注解

复制代码
@SpringBootApplication
@EnableDiscoveryClient//声明为服务消费者
@EnableFeignClients //声明启⽤feign客户端
public class ApiOrderAddFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiOrderAddFeignApplication.class, args);
    }
}

2、服务调⽤

使⽤Feign进⾏服务调⽤的时候,需要⼿动创建⼀个服务访问客户端(接⼝)

2.1、创建Feign客户端

复制代码
@FeignClient("order-add")
public interface OrderAddClient {
    @PostMapping("order/add")
     public ResultVO addOrder(Order order);
}

2.2、使⽤Feign客户端调⽤服务

复制代码
@Service
public class OrderAddServiceImpl implements OrderAddService {
    @AutowiredprivateOrderAddClient orderAddClient;
    @Override
    public ResultVO saveOrder(Order order) {
        //1. 调⽤ order-add服务进⾏保存
        ResultVO vo = orderAddClient.addOrder(order);
        //2. 调⽤ orderitem-add 保存订单快照
        //3. 调⽤ stock-update 修改商品库存
        //4. 调⽤ shopcart-del 删除购物⻋记录
        return vo;
    }
}

3、Feign传参

3.1、POST请求

1、通过请求体传递对象

服务提供者

复制代码
@PostMapping("/add")
public ResultVO addOrder(@RequestBody Order order){
    System.out.println("-------------------order-add");
    System.out.println(order);
    return orderService.saveOrder(order);
}

服务消费者(Feign客户端)

复制代码
@FeignClient("order-add")
public interface OrderAddClient {
    @PostMapping("order/add")
     public ResultVO addOrder(Order order);
}

2、通过请求⾏传参

服务提供者

复制代码
@PostMapping("/add")
public ResultVO addOrder(@RequestBody Order order,String str){
    System.out.println("-------------------order-add");
    System.out.println(order);
    System.out.println(str);
    return orderService.saveOrder(order);
}

服务消费者(Feign客户端)

复制代码
//1.对⽤POST请求调⽤服务,Feign客户端的⽅法参数默认为body传值(body只能有⼀个值)
//2.如果有多个参数,则需要通过@RequestParam声明参数为请求⾏传值
@PostMapping("order/add")
public ResultVO addOrder(Order order,@RequestParam("str") String str);

3、Get请求

Get请求调⽤服务,只能通过url传参在Feign客户端的⽅法中,如果不指定参数的传值⽅式,则默认为body传参,Get请求也不例外;
因此对于get请求传递参数,必须通过@RequestParam注解声明

服务提供者

复制代码
@GetMapping("/get")
public Order addOrder(String orderId){
    return new Order();
}

服务消费者(Feign客户端)

复制代码
@GetMapping("order/get")
public Order getOrder(@RequestParam("orderId") String orderId);

六、服务注册与发现中⼼的可靠性和安全性

1、可靠性

在微服务架构系统中,服务消费者是通过服务注册与发现中⼼发现服务、调⽤服务的,
服务注册与发现中⼼服务器⼀旦挂掉,将会导致整个微服务架构系统的崩溃,如何保证
Eureka的可靠性呢?

  • 使⽤eureka集群
    Eureka集群搭建
    相互注册、相互发现
复制代码
## 设置服务注册与发现中⼼的端⼝
server:
  port: 8761
## 在微服务架构中,服务注册中⼼是通过服务应⽤的名称来区分每个服务的
## 我们在创建每个服务之后,指定当前服务的 应⽤名/项⽬名
spring:
  application:
    name: service-eureka
eureka:
  client:
    ## 设置服务注册与发现中⼼是否为集群搭建
    register-with-eureka: true
    ## 设置服务注册与发现中是否作为服务进⾏注册
    fetch-registry: true
    ## ip 就是服务注册中⼼服务器的ip
    ## port 就是服务注册与发现中⼼设置的port
    service-url:
      defaultZone: 'http://192.168.54.10:8761/eureka'
    

2、安全性

当完成Eureka的搭建之后,只要知道ip和port就可以随意的注册服务、调⽤服务,这是
不安全的,我们可以通过设置帐号和密码来限制服务的注册及发现。

  • 在eureka中整合Spring Security安全框架实现帐号和密码验证

2.1、添加SpringSecurity的依赖

复制代码
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-security</artifactId>
</dependency>

2.2、设置访问eureka的帐号和密码

复制代码
spring:
  security:
    user:
      name: zhangsan
      password: 123456

2.3、配置Spring Security

复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
     protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        // 设置当前服务器的所有请求都要使⽤spring security的认证
        http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
    }
}

2.4、服务提供者和服务消费者连接到注册中⼼都要帐号和密码

复制代码
eureka:
  client:
    service-url:
      defaultZone: 'http://zhangsan:123456@localhost:8761/eureka'

七、熔断器-Hystrix

服务故障的雪崩效应:当A服务调⽤B服务时,由于B服务的故障导致A服务处于阻塞状态,当量的请求可能会导致A服务因资源耗尽⽽出现故障。
为了解决服务故障的雪崩效应,出现了熔断器模型。

1、熔断器介绍


熔断器作⽤:

1、服务降级 :⽤户请求A服务,A服务调⽤B服务,当B服务出现故障或者在特定的时间段内
不能给A服务响应,为了避免A服务因等待B服务⽽产⽣阻塞,A服务就不等B服务的结果
了,直接给⽤户⼀个降级响应
2、服务熔断 :⽤户请求A服务,A服务调⽤B服务,当B服务出现故障的频率过⾼达到特定阈
值(5s 20次)时,当⽤户再请求A服务时,A服务将不再调⽤B服务,直接给⽤户⼀个降
级响应

2、熔断器的原理

3、基于Ribbon服务调⽤的熔断器使⽤

3.1、服务消费者的服务降级

1、添加熔断器依赖 hystrix

复制代码
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

2、在启动类添加 @EnableHystrix 注解

复制代码
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrixpublic class ApiOrderAddApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiOrderAddApplication.class, args);
    }
}

3、在调⽤服务提供者的业务处理⽅法中,进⾏降级配置

复制代码
@Service
public class OrderAddServiceImpl implements OrderAddService {
   @Autowired
   private RestTemplate restTemplate;
   @HystrixCommand(fallbackMethod="fallbackSaveOrder",commandProperties = {
        @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000")
      }    )
   public ResultVO saveOrder(Order order) {
      //1. 调⽤ order-add服务进⾏保存
      //参数1:访问服务的url
      //参数2:传递的对象参数
      //参数3:指定服务提供者返回的数据类型
      ResultVO vo = restTemplate.postForObject("http://order-add/order/add",order, ResultVO.class);
      System.out.println(vo);
      return vo;
  }
  /**
   * 降级⽅法:与业务⽅法拥有相同的参数和返回值
   * @return
   */
  public ResultVO fallbackSaveOrder(Order order){
      return ResultVO.fail("⽹络异常,请重试!",null);
  }
}

3.2、服务提供者的服务降级

1、配置步骤⼀致
2、服务提供者接⼝降级

复制代码
@RestController
@RequestMapping("/order")
public class OrderController {
   @Autowired
   private OrderService orderService;
   @HystrixCommand(fallbackMethod="fallbackAddOrder",commandProperties = {
      @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000") } )
   @PostMapping("/add")
   public ResultVO addOrder(@RequestBody Order order){
      System.out.println("-------------------order-add");
      System.out.println(order);
      try {
          Thread.sleep(5000);
      }
      catch (InterruptedException e) {
          e.printStackTrace();
      }
      return orderService.saveOrder(order);
  }
  public ResultVO fallbackAddOrder(@RequestBody Order order){
      System.out.println("-------------------order-add--fallback");
      return ResultVO.fail("订单保存失败!",null);
  }
}

1、服务熔断配置
熔断器状态:闭合、打开、半开
服务熔断配置

复制代码
  @HystrixCommand(fallbackMethod ="fallbackSaveOrder",commandProperties = {
    @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="3000"),
     @HystrixProperty(name="circuitBreaker.enabled",value="true"),//启⽤服务熔断
    @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="10000"),//时间
    @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10"),//请求次数
    @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value="50"),//服务错误率
    }
  )
  public ResultVO saveOrder(Order order) {
    //1. 调⽤ order-add服务进⾏保存
    ResultVO vo = restTemplate.postForObject("http://orderadd/order/add", order, ResultVO.class);
    System.out.println(vo);
    return vo;
  }
  /**
  * 降级⽅法:与业务⽅法拥有相同的参数和返回值
  * @return
  */
  public ResultVO fallbackSaveOrder(Order order){
    return ResultVO.fail("⽹络异常,请重试!",null);
  }

服务熔断:当⽤户请求服务A,服务A调⽤服务B时,如果服务B的故障率达到特定的
阈值时,熔断器就会被打开⼀个时间周期(默认5s,可⾃定义),在这个时间周期
内如果⽤户请求服务A,服务A将不再调⽤服务B,⽽是直接响应降级服务。

4、基于Feign服务调⽤的熔断器使⽤

Feign是基于Ribbon和Hystrix的封装

4.1、Feign中的熔断器使⽤

1、添加依赖(SpringBoot 2.3.11 、Spring Cloud H)

复制代码
<parent>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-parent</artifactId>
   <version>2.3.11.RELEASE</version>
   <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
   <java.version>1.8</java.version>
   <spring-cloud.version>Hoxton.SR11</spring-cloud.version>
</properties>
复制代码
<dependency>
     <groupId>org.springframework.cloud</groupId>
     <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

2、在application.yml启⽤熔断器机制

复制代码
feign:
  hystrix:
    enabled: true    

3、在启动类添加 @EnableHystrix

复制代码
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrixpublic class ApiOrderAddFeignApplication {
    public static void main(String[] args) {
        SpringApplication.run(ApiOrderAddFeignApplication.class, args);
    }
}

4、创建服务降级处理类

5、FeignClient的服务降级类:

5.1.必须实现Feign客户端接⼝

5.2.必须交给Spring容器管理

复制代码
@Component
public class OrderAddClientFallback implements OrderAddClient {
    public ResultVO addOrder(Order order, String str) {
        System.out.println("-------addOrder的降级服务");
        return ResultVO.fail("fail",null);
    }
    public Order getOrder(String orderId) {
        System.out.println("-------getOrder的降级服务");
        return new Order();
    }
}

6、在Feign客户端指定降级处理类

复制代码
@FeignClient(value = "order-add", fallback =OrderAddClientFallback.class)
public interface OrderAddClient {
    //1.对⽤POST请求调⽤服务,Feign客户端的⽅法参数默认为body传值(body只能有⼀个值)
    //2.如果有多个参数,则需要通过@RequestParam声明参数为请求⾏传值
    @PostMapping("order/add")
    public ResultVO addOrder(Order order,@RequestParam("str") String str);

    @GetMapping("order/get")
    public Order getOrder(@RequestParam("orderId") String orderId);
}

7、Service类通过Feign客户端调⽤服务

复制代码
@Service
public class OrderAddServiceImpl implements OrderAddService {
    @Autowired
    private OrderAddClient orderAddClient;
    //当我们创建Feign客户端的降级类并交给Spring管理后 在Spring容器中就会出现两个OrderAddClient对象
    @Override
    public ResultVO saveOrder(Order order) {
        //1. 调⽤ order-add服务进⾏保存
        ResultVO vo = orderAddClient.addOrder(order,"测试字符串");
        Order order1 = orderAddClient.getOrder("订单编号");
        System.out.println(order1);
        return vo;
    }
}

5、Ribbon 参数配置

复制代码
ribbon:
  ## Ribbon建⽴连接最⼤等待时间
  ConnectTimeout: 1000
  ## 在当前服务提供者尝试连接次数
  MaxAutoRetries: 2
  ## 与服务提供者通信时间
  ReadTimeout: 5000

## 设置熔断器服务降级时间 (默认 1000)
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 8000

6、熔断器仪表盘监控

查看各个服务的熔断器状态面板:

  • 熔断器仪表盘

6.1、搭建熔断器仪表盘

1、创建SpringBoot项⽬,添加依赖

复制代码
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-hystrixdashboard</artifactId>
</dependency>

2、配置仪表盘的port和appName

复制代码
server:
  port: 9999
spring:
  application:
    name: hystrix-dashboard
hystrix:
dashboard:
    proxy-stream-allow-list: localhost

3、启动类添加 @EanbleHystrixDashboard 注解

复制代码
@SpringBootApplication
@EnableHystrixDashboardpublic class HystrixDashboardApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardApplication.class,args);
    }
}

4、访问 http://localhost:9999/hystrix

6.2、配置使⽤了熔断器的服务可被监控

1、添加依赖

复制代码
<dependency>
     <groupId>org.springframework.boot</groupId>
     <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

2、配置(给每个需要监控熔断器的项目配置)

复制代码
@Configuration
public class DashBoardConfig {
     @Bean
     public ServletRegistrationBean getServletRegistrationBean(){
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
        registrationBean.setName("HystrixMetricsStreamServlet");
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        return registrationBean;
    }
}

3、查看指定服务的熔断器⼯作参数

相关推荐
短剑重铸之日3 天前
《SpringCloud实用版》Stream + RocketMQ 实现可靠消息 & 事务消息
后端·rocketmq·springcloud·消息中间件·事务消息
没有bug.的程序员5 天前
Spring Cloud Stream:消息驱动微服务的实战与 Kafka 集成终极指南
java·微服务·架构·kafka·stream·springcloud·消息驱动
没有bug.的程序员6 天前
Spring Cloud Gateway:API网关限流与熔断实战
java·开发语言·数据库·spring boot·gateway·api·springcloud
wfsm9 天前
nacos和openfeign
springcloud
无心水10 天前
【分布式利器:腾讯TSF】11、腾讯TSF微服务框架深度对比:全面解析TSF vs Spring Cloud vs Dubbo vs Service Mesh
分布式·spring cloud·微服务·dubbo·springcloud·service mesh·分布式利器
sunnyday042611 天前
Spring Cloud Alibaba Sentinel 流量控制与熔断降级实战指南
spring boot·sentinel·springcloud
悟空码字14 天前
Spring Cloud 集成 Nacos,全面的配置中心与服务发现解决方案
java·nacos·springcloud·编程技术·后端开发
坐不住的爱码20 天前
Bootstrap和application.yml
springcloud
悟空码字21 天前
Spring Cloud Gateway实战,从零搭建API网关,构建高性能微服务统一入口
java·gateway·springcloud·编程技术·后端开发
没有bug.的程序员22 天前
Service Mesh 与 Spring Cloud 共存方案:双体系治理、平滑迁移与风险控制实战指南
云原生·springcloud·流量治理·混合架构·servicemesh·微服务迁移·技术演进