nacos+feign+Hystrix+gateway使用

本文介绍了如何下载和配置Nacos作为注册中心,通过Spring Cloud实现服务注册与发现,使用Feign进行微服务间调用,并加入Hystrix熔断机制保护,最后结合Spring Cloud Gateway实现服务路由。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、使用nacos(注册中心)

1、下载

2、启动

在\nacos\bin目录下鼠标双击startup.cmd启动

3、访问测试

http://127.0.0.1:8848/nacos/index.html

账号密码都是nacos

登录成功就可以了

4、配置maven依赖

 <!--Spring Cloud 其中springcloud的版本要和springboot版本相对应-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>2021.0.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>0.2.2.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
<!--服务注册-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>com.netflix.ribbon</groupId>
                    <artifactId>ribbon</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

5、在application.properties中添加服务发现地址和自己都服务名

spring.application.name=service-vod
#nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

6、在启动类上加注解

@EnableDiscoveryClient //nocas服务注册发现

@EnableDiscoveryClient //nocas服务注册发现
public class VodApplication {
    public static void main(String[] args) {
        SpringApplication.run(VodApplication.class, args);
    }
}

2、使用feign

使用feign可以拿到注册在nacos的微服务

1、导入maven依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>2021.0.1</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>0.2.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!--服务调用-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-loadbalancer</artifactId>
</dependency>

2、在启动类上加注解

@EnableFeignClients //调用nacos注册的微服务

3、使用

1、创建接口

创建接口,里面调用的远程接口跟远程微服务的控制层方法一模一样

import com.tuzhi.utilcommon.result.Result;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @program: guli_parent
 * @description: 调用远程的Vod微服务
 * @author: 兔子
 * @create: 2022-04-16 15:24
 **/

//name=服务名称
@FeignClient(name = "service-vod")
@Component
public interface VodClient {

    //定义调用的方法路径,方法路径已经要写全
    //根据视频id删除阿里云视频
    //@PathVariable注解一定要指定参数名称,否则出错
    @DeleteMapping("/eduvod/{videoId}")
    public Result deleteVideo(@PathVariable("videoId") String videoId);

}

2、使用@Autowired注入正常使用

3、hystrix使用

熔断器,用于服务器宕机和延长请求时间

1、导入maven依赖

<!--hystrix依赖,主要是用  @HystrixCommand -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.2.10.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>28.0-jre</version>
</dependency>

2、添加application.properties配置

#开启熔断机制
feign.circuitbreaker.enabled=true
# 设置hystrix超时时间,默认1000ms
#hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=6000

3、使用

1.在feign接口的直接上加fallback

//name=服务名称
@FeignClient(name = "service-vod", fallback = VodFileDegradeFeignClient.class)
@Component
public interface VodClient {

    //定义调用的方法路径,方法路径已经要写全
    //根据视频id删除阿里云视频
    //@PathVariable注解一定要指定参数名称,否则出错
    //删除单个视频
    @DeleteMapping("/eduvod/{videoId}")
    Result deleteVideo(@PathVariable("videoId") String videoId);

    //删除多个视频
    @DeleteMapping("/eduvod/deleteBatch")
    public Result deleteVideoBatch(@RequestParam("list") List<String> list);

2.创建一个类基础frign的接口

@Component
public class VodFileDegradeFeignClient implements VodClient {

    @Override
    public Result deleteVideo(String videoId) {
        System.out.println("执行了熔断删除视频出错了");

        return Result.error().message("删除视频出错了");
    }

    @Override
    public Result deleteVideoBatch(List<String> list) {
        System.out.println("执行了熔断删除多个视频出错了");
        return Result.error().message("删除多个视频出错了");
    }
}

4、使用gateway

1、导入maven依赖

<dependencies>

    <dependency>
        <groupId>com.github.ben-manes.caffeine</groupId>
        <artifactId>caffeine</artifactId>
    </dependency>

    <dependency>
        <groupId>com.tuzhi</groupId>
        <artifactId>commonutil</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>

    <!--服务注册-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-loadbalancer</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-gateway</artifactId>

    </dependency>

    <!--gson-->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
    </dependency>

    <!--服务调用-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
</dependencies>

2、编写application.properties

# 服务端口
server.port=8222
# 服务名
spring.application.name=service-gateway
# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

#使用服务发现路由
spring.cloud.gateway.discovery.locator.enabled=true

#spring.cloud.loadbalancer.ribbon.enabled=false
#spring.cloud.loadbalancer.cache.enabled=true
spring.cloud.loadbalancer.cache.caffeine.spec=initialCapacity=500,expireAfterWrite=5s
#设置路由id

#配置service-edu服务
spring.cloud.gateway.routes[0].id=service-edu
#spring.cloud.gateway.routes[0].uri=lb://service-edu
spring.cloud.gateway.routes[0].uri=http://localhost:8001
spring.cloud.gateway.routes[0].predicates= Path=/eduservice/**

#配置service-msm服务
spring.cloud.gateway.routes[1].id=service-msm
spring.cloud.gateway.routes[1].uri=lb://service-msm
spring.cloud.gateway.routes[1].predicates= Path=/edumsm/**

spring.main.web-application-type=reactive

3、在启动类上加注解

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableDiscoveryClient //nacos
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

4、编写config文件

package com.tuzhi.gateway.config;


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.util.pattern.PathPatternParser;

/**
 * <p>
 * 处理跨域
 * </p>
 */
@Configuration
public class CorsConfig {
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedMethod("*");
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}

3、编写filter

package com.tuzhi.gateway.filter;

import com.google.gson.JsonObject;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * <p>
 * 全局Filter,统一处理会员登录与外部不允许访问的服务
 * </p>
 */
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();
        //谷粒学院api接口,校验用户必须登录
        if (antPathMatcher.match("/api/**/auth/**", path)) {
            List<String> tokenList = request.getHeaders().get("token");
            if (null == tokenList) {
                ServerHttpResponse response = exchange.getResponse();
                return out(response);
            } else {
//                Boolean isCheck = JwtUtils.checkToken(tokenList.get(0));
//                if(!isCheck) {
                ServerHttpResponse response = exchange.getResponse();
                return out(response);
//                }
            }
        }
        //内部服务接口,不允许外部访问
        if (antPathMatcher.match("/**/inner/**", path)) {
            ServerHttpResponse response = exchange.getResponse();
            return out(response);
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }

    private Mono<Void> out(ServerHttpResponse response) {
        JsonObject message = new JsonObject();
        message.addProperty("success", false);
        message.addProperty("code", 28004);
        message.addProperty("data", "鉴权失败");
        byte[] bits = message.toString().getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bits);
        //response.setStatusCode(HttpStatus.UNAUTHORIZED);
        //指定编码,否则在浏览器中会中文乱码
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
        return response.writeWith(Mono.just(buffer));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值