1. Nacos的使用
Nacos(相当于Eureka--服务注册中心)
下载地址:Releases · alibaba/nacos · GitHub
(1)下载Nacos压缩包,解压
(2)修改Nacos的配置为单体--这样可以直接双击启动;
启动后访问:http://localhost:8848/nacos/index.html
config里面修改mode=“单机”
(3)连接数据库(将Nacos中的数据持久化到数据库)
在application/properties中 去连接数据库
2. 实现微服务注册到Nacos 实操
2.1 创建项目(创建一个父工程,再创建几个子项目)
2.2 导入父工程依赖
<!--SpringBoot-->
<parent>
<groupId> org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<!--SpringCloud-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
2.3 创建一个order子项目,并导入依赖(服务发现+web包)
<dependency>
<groupId>com.alibaba.cloud </groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.4 order项目启动类
@SpringBootApplication
public class OrderApp
{
public static void main( String[] args )
{
SpringApplication.run(OrderApp.class,args);
}
}
2.5 order项目的yml配置(自身端口,服务名,注册地址)
server:
port: 10010 #自身端口
spring:
application:
name: service-order #服务名
cloud:
nacos:
discovery:
server-addr: localhost:8848 #nacos的注册地址
3. Nacos的配置管理
将微服务的配(yml)交给Nacos管理
3.1 配置管理步骤:
(1)在Nacos云端的服务管理的服务列表写一个配置文件
(2)将要在微服务配置好的yml文件的内容复制给Nacos云端的配置文件
(3)在指定的微服务的pom.xml导入依赖(配置)
(4)在指定的微服务下写一个bootstrap.yaml配置文件(作用:连接云端,读取对应的配置文件)
3.1.1 在Nacos云端的服务管理的服务列表写一个配置文件
3.1.2 将要在微服务配置好的yml文件的内容复制给Nacos云端的配置文件
这里只是该微服务注册到Nacos的配置
server:
port: 10020 #自身端口号
spring:
application:
name: service-user #服务名
cloud:
nacos:
discovery:
server-addr: localhost:8848 #服务发现地址
3.1.3 在指定的微服务的pom.xml导入依赖(配置)
<!-- 配置中心客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
3.1.4 在指定的微服务下写一个bootstrap.yaml配置文件(作用:连接云端,读取对应的配置文件)
spring:
cloud:
nacos:
config:
file-extension: yaml #云端的配置文件名 后缀
prefix: application-user #云端的配置文件的 前缀
server-addr: localhost:8848 #连接配置文件的地址
shared-configs:
- application-dev.yaml #读取云端的公共配置文件的名称
profiles:
active: dev #配置文件的环境
#该云端的配置文件名: application-user-dev.yaml
4. 微服务对OpenFeign的测试(两个微服务间的请求调用;这里也是order和user微服务;order调user)
(1)创建一个pojo-user项目,写一个User类,将该项目通过依赖导入两个微服务
<!-- springCloud-pojo-user 是一个项目,其中写了一个公共的User类 -->
<dependency>
<groupId>com.lh</groupId>
<artifactId>springCloud-pojo-user</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
(2)在调用的微服务(order微服务)的pom.xml中导入OpenFeign依赖(被调用的微服务则不需要导入OpenFeign依赖)
<!-- openfeign的依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
(3)在order的启动类上开启Feign
@EnableFeignClients
@SpringBootApplication
@EnableFeignClients
public class OrderApp {
public static void main(String[] args) {
SpringApplication.run(OrderApp.class, args);
}
}
(4)编写两个微服务的接口;
user接口:
@GetMapping("/user/{id}")
@SentinelResource(value = "user",blockHandler = "getUser")
public User getUsers(@PathVariable("id") Long id){
return new User(id,"hehe"+notify+":"+redis);
}
order接口:
@RestController
public class OrderController {
//注入Feign接口
@Autowired
private UserFeignClient userFeignClient;
@GetMapping("/order/{id}")
public User getUsers(@PathVariable("id") Long id){
return userFeignClient.getUsers(id);
}
}
(5)编写注入到Ordercontroller的userFeignClient接口
import com.lh.domain.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//value = "service-user"--这是调用指定的微服务的服务名
@FeignClient(value = "service-user")
public interface UserFeignClient {
//这里要和user微服务的controller对应的方法保持一致
@GetMapping("/user/{id}")
User getUsers(@PathVariable("id") Long id);
}
(6)输入:http://localhost:10010/order/3
5. Sentinel
Sentinel相当于是Hystrix
5.1 Sentinel服务端下载
(1)下载jar包 https://github.com/alibaba/Sentinel/releases/download/1.6.0/sentinel-dashboard-1.6.0.jar
(2)双加jar包,输入:java -jar Dserver.port=1111 sentinel-dashboard-1.6.0.jar
备注:sentinel-dashboard-1.6.0.jar --jar包的全称
(3)访问:http://localhost:1111
5.2 Sentinel对user服务的一个后端接口方法实现限流
(1)在user服务的pom.xml中导入依赖
<!-- sentinel依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
(2)yml配置(将user服务连接到sentinel;sentinel服务可以限流和熔断服务)
spring:
cloud:
sentinel:
transport:
dashboard: localhost:1111
(3)user的controller接口(注意:@SentinelResources中的value是sentinel云端的资源名;通过该资源名可以对其进行限流,熔断)
package com.lh.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.lh.domain.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
public class UserController {
@GetMapping("/user/{id}")
@SentinelResource(value = "user",blockHandler = "getUserblockHandler")
public User getUsers(@PathVariable("id") Long id){
return new User(id,"hehe"+notify+":"+redis);
}
public User getUserblockHandler(@PathVariable("id") Long id, BlockException blockException){
blockException.printStackTrace();
System.out.println("限流");
return new User(2L,"限流");
}
(4)在sentinel的云端设置限流
点击流控:(单击阀值表示规定时间内同时请求该方法的请求次数)
备注:这里设置为2;当在1S内访问:http://localhost:10020/user/2 两次会触发限流提示。限流方法的返回值类型、参数列表要和被限流的方法一致。
6. 上述是普通微服务中使用Sentinel;
下面是Gateway使用Sentinel
6.1 步骤:
(1)创建一个Gateway项目
(2)导入依赖
基础依赖:注意:这里不必导入web包
<!-- gateway依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud </groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
加上配置依赖和集成sentinel依赖
<!-- 配置中心客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 限流和gataway使用-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
(3)启动类
@SpringBootApplication
public class GatewayApp {
public static void main(String[] args) {
SpringApplication.run(GatewayApp.class, args);
}
}
(4)yml配置(这里导入了config,可以将配置文件交给Nacos)
server:
port: 10030
spring:
application:
name: hehe-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
httpclient: #配置超时
connect-timeout: 1000
response-timeout: 5s
discovery:
locator:
enabled: false #开放服务名访问方式
lower-case-service-id: true #服务名小写
routes:
- id: service-user #指定服务名
uri: lb://service-user #去注册中心找这个服务名
predicates: #断言,匹配访问的路径
- Path=/services/user/** #服务访问路径
filters:
- StripPrefix=2 #请求转发的时候会去掉 /user访问路径
- id: service-order #指定服务名
uri: lb://service-order #去注册中心找这个服务名
predicates: #断言,匹配访问的路径
- Path=/services/order/** #服务访问路径
filters:
- StripPrefix=2 #请求转发的时候会去掉 /user访问路径
(5)编写一个bootstrap.yaml,去连接云端的配置文件
spring:
profiles:
active: dev
cloud:
nacos:
config:
prefix: application-gateway
file-extension: yaml
server-addr: localhost:8848 #该地址为Nacos云端地址
sentinel: #连接sentinel的云端
transport:
dashboard: localhost:1111
(6)写一个配置类
@Configuration
public class SentinelConfig {
public SentinelConfig(){
GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
return ServerResponse.ok().body(Mono.just("限流啦,请求太频繁"),String.class);
}
});
}
}
(7)在云端可以找到hehe-gateWay;通过访问:http:localhost:10030/services/order/order/2
或者http:localhost:10030/services/user/user/2 ,可以在请求链路中获取order的服务名或者user的服务名;可以对上述的请求做出限流和熔断。
7.Nacos持久化sentinel
思路:例如将user服务的配置交个nacos,通过启动user服务在读取配置文件时,可以通过配置文件修改sentinel云端的数据
7.1 步骤(这里是对user服务操作)
(1)在user的pom.xml中导入依赖
<!--Sentinel和Nacos做持久的-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.5.2</version>
</dependency>
(2)在nacos云端创建一个配置文件:application-sentinel-user-dev
备注:配置文件上hijson格式
[
{
"resource": "user",
"limitApp": "default",
"grade": 1,
"count": 4,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}
]
-
resource:对那个资源进行限流
-
limitApp:这个是流控的调用者,default 代表不区分调用者
-
grade:限流方式0是根据并发数量限流,1是表根据QPS来限流
-
count:限流阈值,达到这个阈值就被限流,触发降级。
-
strategy:基于调用链的流控制策略。0 直接,1 关联 2 链路
-
controlBehavior:流控效果,0 直接拒绝,1是Warm Up,2是匀速排队
-
clusterMode:是否为集群
(3)启动:http://localhost:10020/user/2 可以在sentinel的云端看到user服务名对应的一个资源名:user
8. Sentinel熔断
8.1 对user服务进行熔断测试
在@SentinelResources中加 fallback=“熔断方法” --(和限流方法的规则一致)
package com.lh.controller;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.lh.domain.User;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope
public class UserController {
@GetMapping("/user/{id}")
@SentinelResource(value = "user",fallback = "getUserFallback")
public User getUsers(@PathVariable("id") Long id){
return new User(id,"hehe"+notify+":"+redis);
}
public User getUserFallback(@PathVariable("id") Long id){
return new User(2L,"熔断");
}
}
8.2 OpenFeign整合Sentinel熔断(由于order服务用了OpenFeign,所以这里以order服务测试)
步骤:
(1)导入依赖
<!-- sentinel依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
(2)配置yaml
feign: #开启sentinel
sentinel:
enabled: true
(3)在OpenFeign的基础上添加降级功能
@FeignClient(value = "server-user",fallback = OrderBack.class)
//
public interface UserFeignClient {
//这里要和user微服务的controller对应的方法保持一致
@GetMapping("/user/{id}")
User getUsers(@PathVariable("id") Long id);
}
(4)编写降级类
package com.lh.back;
import com.lh.clients.UserFeignClient;
import com.lh.domain.User;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;
@Component
public class OrderBack implements UserFeignClient{
@Override
public User getUsers(Long id) {
return new User(2L,"jiangji");
}
}
每日面试
-
SpringCloud和SpringCoudAlibaba的区别
-
Nacos用来做什么?
-
Sentinel可以如何限流
-
Sentinel的流控模式有哪些?
-
Sentinel的流控效果有哪些