①pom.xml文件引入eureka依赖 spring-cloud-starter-netflix-eureka-serve
②启动类添加注解 @EnableEurekaServer 在项目启动类上使用@EnableEurekaServer,可以将模块作为SpringCloud中的注册中心,提供服务注册和发现的能力
③配置application.yml
server:
port: 8761 # 注册中心端口
spring:
application:
name: eurekaserver # eureka的服务名称
eureka:
client:
serviceUrl: #注册中心访问地址
defaultZone: http://localhost:8761/eureka/
registerWithEureka: false #是否注册自己,服务端就不用了注册自己了
fetchRegistry: false #是否从其他注册中心导入数据
①pom.xml文件引入eureka依赖 spring-cloud-starter-netflix-eureka-client
②配置application.yml
server:
port: 8763
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_order?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
username: root
password: zks123456
driver-class-name: com.mysql.cj.jdbc.Driver
application:
name: orderservice
mybatis:
type-aliases-package: com.gzhu.pojo
configuration:
map-underscore-to-camel-case: true
mapper-locations: classpath:mybatis/mapper/*.xml
eureka: #注册中心地址
client:
service-url:
defaultZone: http://localhost:8761/eureka/
①pom.xml文件引入eureka依赖 spring-cloud-starter-netflix-eureka-client
②配置application.yml
server:
port: 8763
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_order?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
username: root
password: zks123456
driver-class-name: com.mysql.cj.jdbc.Driver
application:
name: orderservice
mybatis:
type-aliases-package: com.gzhu.pojo
configuration:
map-underscore-to-camel-case: true
mapper-locations: classpath:mybatis/mapper/*.xml
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
③启动类添加RestTemplate以及@LoadBalanced注解(用于负载均衡)
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
④使用服务名称调用,如userservice就是一个微服务的名称
public Order queryOrderById(Long orderId) {
//1.查询订单
Order order = orderMapper.findById(orderId);
//2.利用RestTemplate发起http请求,查询用户
String url = "http://userservice/user/"+order.getUserId();
User user = restTemplate.getForObject(url, User.class);
order.setUser(user);
return order;
}
默认的负载均衡策略是轮询,可以通过两种方式改为随机方式
①代码方式
在某一个微服务的启动类
定义一个新的IRule
@Bean
public IRule randonRule(){
return new RandonRule();
}
则该微服务访问任何微服务的策略均为随机访问
②配置文件
在某个微服务的配置文件中添加以下配置,则针对该微服务的访问是随机
userservice:
ribbon:
NFLoadBalancerRuleClassName:com.netflix.loadbalancer.RandomRule# 负载均衡规则
Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:
ribbon:
eager-load:
enabled: true # 开启饥饿加载
clients: userservice # 指定对userservice这个服务饥饿加载
cmd进入nacos的bin目录 输入startup.cmd -m standalone即可启动
输入网址即为nacos的控制台
父工程pom.xml引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>SpringCloud</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>eureka-server-8761</module>
<module>config-server-8762</module>
<module>order-server-8763</module>
<module>user-server-8764</module>
<module>feign-api</module>
<module>gateway</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.12</version>
<relativePath/>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.alibaba.version>2021.1</spring-cloud.alibaba.version>
<mysql.version>8.0.27</mysql.version>
<mybatis.version>2.2.0</mybatis.version>
</properties>
<dependencyManagement>
<dependencies>
<!--nacos的管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--mysql驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${m才ybatis.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.22</version>
</dependency>
</dependencies>
</project>
微服务引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SpringCloud</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>user-server-8764</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--nacos客户端依赖包 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--nacos的配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.4</version>
</dependency>
</dependencies>
</project>
application.yml进行配置,nacos默认端口为8848
一级是服务,例如userservice
二级是集群,例如杭州或上海
三级是实例,例如杭州机房的某台部署了userservice的服务器
①搭建集群
配置文件集群名为GZHU,先启动两个实例,再修改配置文件的集群名称为QAU,再启动最后一个实例
spring:
cloud:
nacos:
server-addr: localhost:8848
discovery:
cluster-name:XXX #XXX自定集群名
userservice创建两个集群,其中集群GZHU包含两个实例,QAU包含一个实例
②当调用微服务时,默认访问是随机的,即任何一个集群的微服务都可能被选到。如果在userservice配置文件配置以下信息,则访问会优先访问本地集群即优先访问GZHU集群的两个微服务,当本地集群挂掉后,则会跨集群访问即访问QAU集群,但这时会报一个跨集群警告
userservice:
ribbon:
NFLoadBalancerRuleClassName:com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则
③访问权重设置
Nacos控制台可以设置实例的权重值,0~1之间
同集群内的多个实例,权重越高被访问的频率越高
权重设置为0则完全不会被访问
默认所有的微服务都在public环境中
新建命名空间
命名空间id
配置文件配置命名空间,则该微服务会到相应的空间,与其他空间的微服务没有任何交集
①控制台编写配置文件
②读取配置文件
首先需要导入config依赖
<!--nacos的配置管理依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.4</version>
</dependency>
然后在userservice中的resource目录添加一个bootstrap.yml文件,这个文件是引导文件,优先级高于application.yml。在微服务中添加bootstrap.yml,配置nacos地址、当前环境、服务名称、文件后缀名。这些决定了程序启动时去nacos读取哪个文件
这里建议使用低版本的config依赖,高版本的依赖需要额外导入bootstrap依赖
spring:
application:
name: userservice #服务名称
profiles:
active: dev #开发环境
cloud:
nacos:
config:
server-addr: localhost:8848 #nacos地址
file-extension: yaml #文件后缀名
③测试
时间格式按照配置文件生成,说明配置文件生效
④热部署配置文件
Nacos中的配置文件变更后,微服务无需重启就可以感知
方式一:在@Value注入的变量所在类上添加注解@RefreshScope
方式二:使用@ConfigurationProperties注解
@Component
@Data
@ConfigurationProperties(prefix = "pattern")
public class PatternProperties {
private String dateformat;
}
⑤多环境配置共享
需要在控制台创建一个配置文件名为XXX.yaml,XXX为服务名,这样该服务的不同实例均可以在启动时读取到配置的信息(IDEA中无需配置任何信息)
优先级:
[服务名]-[环境].yaml >[服务名].yaml > 本地配置(application.yml)
①引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.0.4</version>
</dependency>
②启动类添加注解 @EnableFeignClients
③编写Client接口
@FeignClient("userservice") #指定服务名
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
④使用Client接口进行调用
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private UserClient userClient;
public Order queryOrderById(Long orderId) {
Order order = orderMapper.findById(orderId);
User user = userClient.findById(order.getUserId());
order.setUser(user);
return order;
}
}
feign:
client:
config:
default: # 这里用default就是全局配置,如果是写服务名称,则是针对某个微服务的配置
loggerLevel: FULL # 日志级别
①日志级别尽量用basic
②连接池优化 HttpClient或OKHttp代替URLConnection(默认连接池)
引入依赖
<!--httpClient的依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
配置参数
feign:
client:
config:
default:
loggerLevel: FULL
httpclient:
enabled: true
max-connections: 200 # 最大的连接数
max-connections-per-route: 50 # 每个路径的最大连接数
统一编写一个Module模块feign-api,用来管理所有的feign接口
①引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.0.4version>
</dependency>
②编写接口即可(相关的pojo全部引入)
@FeignClient("userservice")
public interface UserClient {
@GetMapping("/user/{id}")
User findById(@PathVariable("id") Long id);
}
③消费者使用方式
1.首先也要导入spring-cloud-starter-openfeign依赖(如果版本较新,还需要导入spring-cloud-loadbalancer依赖)
2.在启动类上指定要使用的FeignClient字节码 @EnableFeignClients(clients = {UserClient.class})
3.并且注入相关的接口
@Autowired
private UserClient userClient;
即可正常使用feign-api中所定义的接口
身份认证和权限校验:对用户请求做身份认证、权限校验
服务路由、负载均衡:将用户请求路由到微服务,并实现负载均衡
请求限流:对用户请求做限流
①引入依赖
<dependencies>
<!--nacos服务注册发现依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--网关gateway依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>3.0.0</version>
</dependency>
<!--fegin组件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-loadbalancer</artifactId>
<version>3.0.4</version>
</dependency>
</dependencies>
②编写启动类及配置文件
server:
port: 10010 # 网关端口
spring:
application:
name: gateway # 服务名称
cloud:
nacos:
server-addr: localhost:8848 # nacos地址
gateway:
routes: # 网关路由配置
- id: user-service # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求
- id: order-service # 路由id,自定义,只要唯一即可
# uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
uri: http://127.0.0.1:8763 # 路由的目标地址 lb就是负载均衡,后面跟服务名称
predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
- Path=/order/** # 这个是按照路径匹配,只要以/user/开头就符合要求
详情链接: https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
全局过滤器的作用是什么?
对所有路由都生效的过滤器,并且可以自定义处理逻辑
实现全局过滤器的步骤?
1.实现GlobalFilter接口
2.添加@Order注解(过滤器顺序)或实现Ordered接口
3.编写处理逻辑
@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//1.获取请求参数
MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
// 2.获取authorization参数
String auth = params.getFirst("authorization");
//3.校验
if ("admin".equals(auth)) {
//放行
return chain.filter(exchange);
}
//4.拦截
//4.1禁止访问
exchange.getResponse().setRawStatusCode(HttpStatus.SC_UNAUTHORIZED);
//4.2处理结束
return exchange.getResponse().setComplete();
}
}
过滤器执行顺序:
①order值越小,优先级越高
②当order值一样时,顺序是defaultFilter最先,然后是局部的路由过滤器,最后是全局过滤器