spring cloud alibaba 快速上手

spring cloud alibaba

第一步我们需要创建一个父工程,引入对应的依赖,参考对应版本引入

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 <properties>
 <!--规定好版本,-->
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.1.4.RELEASE</spring-boot.version>
        <alibaba-spring.version>2.1.3.RELEASE</alibaba-spring.version>
        <cloud-spring.version>Greenwich.SR1</cloud-spring.version>
    </properties>
    <packaging>pom</packaging>
    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>2.0.3</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <artifactId>spring-boot-starter-parent</artifactId>
                <groupId>org.springframework.boot</groupId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${cloud-spring.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${alibaba-spring.version}</version>
                <type>pom</type> <!--pom,import是不能省略的-->
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

首先dependencyManagement里面的依赖,类似是子模块中父模块,因为标签只能引入一个父模块,所以需要这种写法,

nacos使用

  • 首先下载对应的版本的nacos
  • 创建一个子客户端模块,并引入nacos依赖
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--        使用nacos注册与发现-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
    </dependencies>
  • 编写配置文件
spring:
  application:
    name: consumer  # nacos中注册的服务名
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848   # nacos地址

server:
  port: 80
  
  • 创建一个服务端子模块,引入nacos依赖
  • 编写配置文件
spring:
  application:
    name: payment-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

server:
  port: 8001

这样两个都注册到了nacos中心里,客户端在访问服务端的时候不需要指明具体的url地址

客户端使用restTemplate 访问服务端的接口

以下是服务端接口

@RestController
public class payCon {

    @Value("${server.port}")
    String port;


    @GetMapping("/pay")
    public String pay() {
        return "pay success" + port;
    }
 
 
}

客户端之前访问肯定是
restTempalte.get(‘http://localhost:端口/pay’)这种一点不友好
现在客户端配置rabbion实现负载均衡,访问只需要服务名即可

以下是客户端代码



 
/**
 * @create 2023-04-02 16:35:05
 *//*
@author ljj
@date 2023-04-02 16:35
*/
@Configuration
public class Config {
    @Bean
    @LoadBalanced  //如果不加负载均衡则不能调用服务名
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}


@RestController
public class ConController {
    @Autowired
    RestTemplate restTemplate;

    @GetMapping("/topay")
    public String toPay() {

        String forObject = restTemplate.getForObject("http://payment-service/pay", String.class);
        return forObject;
    }
}

这样一来就能够顺利调用

nacos 配置文件中心

基本上都会用的到,配置文件会有很多公共的地方,这些我们将它统一配置起来
使用方法也很简单

  • 引入依赖
    <!--        服务配置-->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
    </dependency>

编写配置文件,这里我们用的是bootstrap.yml,这个配置文件的优先级最高

spring:
  application:
    name: nacos_config  
  cloud:
    nacos:
      server-addr: localhost:8848  
      config:
        file-extension: yaml    #因为配置文件中心默认读取的是properties文件,如果nacos中的配置文件格式改了,那么这里需要进行配置,否则读取不到文件
        shared-configs[0]: #自定义配置文件data-id,可以配置多个,自定义的配置文件
          data-id: demo.yml
          refresh: true
        shared-configs[1]:
          data-id: demo-mysql.yml
          refresh: true

然后将会从nacos配置中心读取配置文件

使用openfeign调用服务

正常情况下,客户端访问服务端的时候会使用openfeign来访问比较方便。以下是使用方法

  • 首先添加依赖,只需要客户端添加即可
  <!-- openfeign服务调用 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

服务端的代码不需要更换

  • 启动类需要添加注解 @EnableFeignClients(basePackages = “那个包下”)
  • openfeign 接口,这里的返回类型,方法名、请求参数等要与服务端写的接口一致,正常直接复制拿过来即可
package com.openFeign.service;

import com.entity.People;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

/**
 * @create 2023-04-03 09:30:11
 *//*
@author ljj
@date 2023-04-03 9:30
*/
@Service
@FeignClient(value = "payment-service" )//指明服务端的服务名
public interface FeignService {
    @GetMapping("/pay")
    public String toPay();


    //    地址传参 get?name=?
    @GetMapping("/param")
    public String senPrams(@RequestParam("name") String name);

    //路径传参/param/xxx
    @GetMapping("/param/{name}")
    public String pathParams(@PathVariable("name") String name);

    //传递实体参数
    @PostMapping("/save")
    public People save(@RequestBody People people);
}

使用方法就是和平时的使用mvc接口访问一样,在客户端进行调用就行

以下是服务端接口


/**
 * @create 2023-04-02 16:33:52
 *//*
@author ljj
@date 2023-04-02 16:33
*/
@RestController
public class payCon {

    @Value("${server.port}")
    String port;


    @GetMapping("/pay")
    public String pay() {
        return "pay success" + port;
    }


    @GetMapping("/param")
    public String getParams(@RequestParam("name") String name) {
        return name;
    }

    @GetMapping("/param/{name}")
    public String pathParams(@PathVariable("name") String name) {
        return name + "---";
    }


    //接收实体参数
    @PostMapping("/save")
    public People getPeople(@RequestBody People people) {
        int a = 10 / 0;
        return people;
    }
}

客户端中调用openfeign,其实将那个接口注入进来就行,别的就正常调用即可


/**
 * @create 2023-04-03 09:29:57
 *//*
@author ljj
@date 2023-04-03 9:29
*/
@RestController
public class FeignController {
    @Autowired
    FeignService feignService;

    @GetMapping("/to_pay")
    public String toPay() {
        return feignService.toPay();
    }

    @GetMapping("/param")
    public String senPrams(@RequestParam("name") String name) {
        return feignService.senPrams(name);
    }

    @GetMapping("/param/{name}")
    public String pathParams(@PathVariable("name") String name) {
        return feignService.pathParams(name);
    }

    @GetMapping("/save")
    public Object save() {
        People people = new People();
        people.setName("李俊杰");
        people.setSex("男");

        return feignService.save(people);
    }
}

sentinel 熔断降级

通常使用服务端,防止服务出错而展示的不友好信息

  • 添加相关依赖
<!--        sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
  • 修改配置文件
spring:
  application:
    name: sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080  #需要自己下载对应版本的sentinel客户端,并启动

  • 接口使用
package com.payment.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.entity.People;
import org.apache.tomcat.jni.Time;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.TimeUnit;

/**
 * @create 2023-04-02 16:33:52
 *//*
@author ljj
@date 2023-04-02 16:33
*/
@RestController
public class payCon {

    @Value("${server.port}")
    String port;


    @GetMapping("/pay")
    @SentinelResource(value = "pays", blockHandler = "payHandler")//当接口出现熔断降级,则会触发payHandler方法,并响应
    public String pay() {
        return "pay success" + port;
    }


    @GetMapping("/get")
    @SentinelResource(value = "get", blockHandler = "getHandler")
    public String get() {
        return "获取成功!";
    }

    public String getHandler(BlockException blockException) {

        return "限流!";
    }


    public String payHandler(BlockException blockException) {
        return "请稍后响应";
    }

    @GetMapping("/param")
    public String getParams(@RequestParam("name") String name) {
        return name;
    }

    @GetMapping("/param/{name}")
    @SentinelResource(value = "param",blockHandler = "pathParamHandler")
    public String pathParams(@PathVariable("name") String name) {
        return name + "---";
    }

    public String pathParamHandler(String name,BlockException blockException){
        return "热点数据限流";
    }


    //接收实体参数
    @PostMapping("/save")
    public People getPeople(@RequestBody People people) {
        int a = 10 / 0;
        return people;
    }

    //线程数降级
    @GetMapping("/thr")
    public String thre() throws InterruptedException {
        Thread.sleep(3000);
        return "ok";
    }

    //异常降级
    @GetMapping("/err")
    public String err() throws InterruptedException {
        int a = 10 / 0;
        return "ok";
    }
}

SentinelResource注解修饰的是个性化的熔断降级方案,如果不添加改注解,则使用默认的方案,我们也可以重写默认的全局熔断降级方案,但是不影响个性化的

//没被SentinelResource修饰的接口出错后,则会使用该方案




package com.payment.exec;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;

/**
 * @create 2023-04-05 17:12:47
 *//*
@author ljj
@date 2023-04-05 17:12
*/
@Component
public class SentinelException implements BlockExceptionHandler {
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
        System.out.println(e instanceof SystemBlockException);
        PrintWriter writer = httpServletResponse.getWriter();

        writer.write(new ObjectMapper().writeValueAsString("服务被sentinel限制!"));
        writer.flush();

    }
}

openfeign-sentinel整合

  • 所有依赖

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- openfeign服务调用 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
    </dependencies>
  • 配置
spring:
  application:
    name: openfeign-sentinel
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
    sentinel:
      transport:
        dashboard: localhost:8080


server:
  port: 8003
feign:
  sentinel:
    enabled: true  #启动

  • service层
package com.cloud.service;

import com.cloud.service.impl.FenSenServiceImpl;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @create 2023-04-08 10:21:21
 */
@FeignClient(value = "sentinel-service", fallback = FenSenServiceImpl.class)//fallback熔断降级后的处理
public interface FenSenService {

    @GetMapping("/pay/payment")
    public String payment(@RequestParam("name") String name);
}

如果该接口对应的服务出现错误,则会返回这里的信息

package com.cloud.service.impl;

import com.cloud.service.FenSenService;
import org.springframework.stereotype.Component;

/**
 * @create 2023-04-08 10:22:23
 *//*
@author ljj
@date 2023-04-08 10:22
*/
@Component
public class FenSenServiceImpl implements FenSenService {
    @Override
    public String  payment(String name) {
        return "付款失败,服务异常!";
    }
}

gateway 网关 sentinel可以合用

  • 引入依赖
   <!--    spring cloud gateway整合sentinel的依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
            </dependency>

            <!--    sentinel的依赖-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>

  • 配置
server:
  port: 8088
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      #路由规则
      routes:
        - id: openfeign_sentinel_route #路由的唯一标识
          uri: lb://openfeign-sentinel  #需要转发的地址 lb: 使用nacos中的本地负载均衡
          #断言规则,用于路由规则的匹配,输入url的时候需要前缀/gateway后面才能够正常访问
          predicates:
            - Path=/gateway/**
          filters:
            - StripPrefix=1  #转发之前去掉第一层路径

    sentinel:
      transport:
        dashboard: 127.0.0.1:8080

测试访问
localhost:8088/gateway/feign/pay

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值