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));
}
}