Nacos
Nacos 服务注册与发现
直接下载解压,启动
startup.cmd -m standalone
访问
http://192.168.1.4:8848/nacos/index.html
功能
- 服务发现与管理
- 配置管理
服务注册
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
配置
spring:
application:
name: nacos-discovery-consumer
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
metadata:
name: lengleng
server:
port: 8050
开启服务
@EnableDiscoveryClient //启用服务注册与发现
@SpringBootApplication
public class NacosDiscoveryConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(NacosDiscoveryConsumerApplication.class, args);
}
}
观察nacos控制台查看是否被注册进去
远程方法调用
注册RestTemplate
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
使用
@RestController
public class DemoController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private LoadBalancerClient loadBalancerClient;
@GetMapping("/demo")
public String test01(String name) {
ServiceInstance choose = loadBalancerClient.choose("nacos-discovery-provider");
URI uri = choose.getUri();
return restTemplate.getForObject(uri+"/demo?name=" + name, String.class);
}
}
Nacos负载均衡、服务上下线、权重信息
服务上下线
通过在控制面版进行控制
负载均衡
@Bean
@LoadBalanced //默认集成了ribbon 可以实现负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
直接使用服务名去调用
@GetMapping("/demo")
public String test01(String name) {
//nacos默认集成了 rabbion 因此可以直接使用服务名去调用 来实现负载均衡
return restTemplate.getForObject("http://nacos-discovery-provider/demo?name=" + name, String.class);
}
权重
管理台进行设置,通过编辑按钮进行设置
元数据
上图可以看到有元数据一列,来区分不同的服务节点
获取元数据
@GetMapping("/test")
public String test(String name) {
//获取元数据 感知节点信息
RibbonLoadBalancerClient.RibbonServer ribbonServer = (RibbonLoadBalancerClient.RibbonServer) loadBalancerClient.choose("nacos-discovery-provider");
NacosServer nacosServer = (NacosServer) ribbonServer.getServer();
//第一次 使用rabbion选择了一个provider 获取它的元数据
System.out.println("-->" + nacosServer.getMetadata());
// 这里选择了两次的 provider服务
//第二次又通过rabbion 调用了一次provider 进行具体业务处理
return restTemplate.getForObject( "http://nacos-discovery-provider/demo?name=" + name, String.class);
// 灰度 灰度发布
}
Nacos整合Feign、Webflux
Feign
Feign是从Netflix中分离出来的轻量级项目,能够在类接口上添加注释,成为一个REST API客户端。
通常使用的是open feign
Spring Cloud在netflix fegn的基础上扩展了支持SpringMVC注释,并通过自动配置为Spring Boot应用程序提供集成。
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
配置
spring:
application:
name: nacos-discovery-consumer-feign
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
metadata:
name: lengleng
server:
port: 8052
启用feign
@EnableFeignClients //feign注解
@EnableDiscoveryClient
@SpringBootApplication
public class NacosDiscoveryConsumerFeignApplication {
public static void main(String[] args) {
SpringApplication.run(NacosDiscoveryConsumerFeignApplication.class, args);
}
}
@RestController
public class DemoController {
@Autowired
private DemoFeignService demoFeignService;
@GetMapping("/test")
public String test(String name) {
return demoFeignService.demo(name);
}
}
远程接口
@FeignClient("nacos-discovery-provider")
public interface DemoFeignService {
@GetMapping("/demo")
String demo(@RequestParam("name") String name);
}
Webflux
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
配置
spring:
application:
name: nacos-discovery-consumer-webflux
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
metadata:
name: lengleng
server:
port: 8053
使用
@Bean
@LoadBalanced
public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
@RestController
public class DemoController {
@Autowired
private WebClient.Builder webclientBuilder;
@GetMapping("/test")
public Mono<String> test(String name) {
return webclientBuilder.build()
.get()
.uri("http://nacos-discovery-provider/demo?name=" + name)
.retrieve()
.bodyToMono(String.class);
}
}
Nacos整合gateway
Spring Cloud Gateway是Spring Cloud 的一个全新项目,该项目是基于Spring 5.0,Spring Boot 2.0和ProjectReactor等技术开发的网关,它旨在为微服务架构提供—种简单有效的统一的API路由管理方式。
Spring Cloud Gateway 作为Spring Cloud生态系统中的网关,目标是替代Netflix Zuul,其不仅提供统一的路由方式,并且基于Filter 链的方式提供了网关基本的功能,例如︰安全、监控、埋点和限流等。
配置
添加依赖
不需要引用web模块
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
配置
spring:
application:
name: nacos-discovery-gateway-server
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
metadata:
name: lengleng
gateway:
routes:
- id: nacos-discovery-provider #provider服务的名称
uri: lb://nacos-discovery-provider #nacos注册名称
predicates: #谓词:
- Path=/provider/** #接收的请求
filters:
- StripPrefix=1 # 去掉前缀
server:
port: 8054
Nacos配置中心
配置中心的功能
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
配置bootstrap.yml
# 需要在bootstrap.yml 中进行配置server-addr 由他的声明周期来决定 而不能使用application.yml文件进行配置
spring:
application:
name: nacos-config-client
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yml # 指定文件类型 nacos-config-client.yml 默认是properties
profiles:
active: dev #指定文件后缀来指定环境 nacos-config-client-dev.yml
server:
port: 8055
# 要去加载nacos-config-client-dev.yml文件 读取其中的属性 可以由配置中心进行配置
使用
@RefreshScope //声明是可以进行刷新的 也就是配置文件发生了更改 它可以感知的到
@RestController
public class DemoController {
@Value("${test:空test}")
public String str;
@GetMapping("/test/config")
public String test() {
return str;
}
}
动态配置服务可以让您以中心化、外部化和动态化的方式管理所有环境的应用配置和服务配置。动态配置消除了配置变更时重新部署应用和服务的需要,让配置管理变得更加高效和敏捷。
配置中心化管理让实现无状态服务变得更简单,让服务按需弹性扩展变得更容易。
Nacos提供了一个简洁易用的UI(控制台样例Demo)帮助您管理所有的服务和应用的配置。Nacos还提供包括配置版本踪、金丝雀发布、一键回滚配置以及客户端配置更新状态跟踪在内的一系列开箱即用的配置管理特性,帮助您更安全地在生产环境中管理配置变更和降低配置变更带来的风险。
服务id即dataId生成的策略
即
配置文件加载
profile
读取日志
2019-03-03 12:44:29.040 INFO 23952 --- [-127.0.0.1_8848] o.s.c.a.n.c.NacosPropertySourceBuilder : Loading nacos data, dataId: 'nacos-config-client-load.yml', group: 'DEFAULT_GROUP'
2019-03-03 12:44:29.044 INFO 23952 --- [-127.0.0.1_8848] o.s.c.a.n.c.NacosPropertySourceBuilder : Loading nacos data, dataId: 'nacos-config-client-load-dev.yml', group: 'DEFAULT_GROUP'
后加载的会覆盖掉前面的配置信息
- 优先使用配置是 applicationname-profile
不存在时读取 applicationname
# 需要在bootstrap.yml 中进行配置server-addr 由他的声明周期来决定 而不能使用application.yml文件进行配置 spring: application: name: nacos-config-client cloud: nacos: config: server-addr: 127.0.0.1:8848 file-extension: yml # 指定文件类型 nacos-config-client.yml 默认是properties group: PIGX #组 profiles: active: dev #指定文件后缀来指定环境 nacos-config-client-dev.yml server: port: 8055 # 要去加载nacos-config-client-dev.yml文件 读取其中的属性 可以由配置中心进行配置
GROUP
- 默认没有组 都是放在DEFAULT_GROUP(即DEFAULT_GROUP 是默认的组)
会在新建配置时指定组
匹配顺序
组—-profile
namespace
# 需要在bootstrap.yml 中进行配置server-addr 由他的声明周期来决定 而不能使用application.yml文件进行配置
spring:
application:
name: nacos-config-client
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yml # 指定文件类型 nacos-config-client.yml 默认是properties
group: PIGX #组
namespace: b47c4714-f86e-4234-ad21-1e7fe654f5d5
profiles:
active: dev #指定文件后缀来指定环境 nacos-config-client-dev.yml
server:
port: 8055
# 要去加载nacos-config-client-dev.yml文件 读取其中的属性 可以由配置中心进行配置
namespace需要通过命名空间ID进行指定
加载顺序
namespace—-组—-profile
共享配置文件
spring:
application:
name: nacos-config-client-load
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yml
namespace: b47c4714-f86e-4234-ad21-1e7fe654f5d5
group: PIGX
# 方式一 常用
ext-config:
- data-id: common.yml
group: PIGX
refresh: true
# 方式二 只会加载DEFAULT_GROUP中的配置文件 不会传递group 会传递namespace
shared-dataids: common.yml
refreshable-dataids: common.yml #支持刷新
server:
port: 8056
加载顺序
- common.yml group:DEFAULT_GROUP shared配置的
- commom.yml group:PIGX ext-config配置的
- nacos-config-client-load.yml group:PIGX 默认的
后加载的文件属性会覆盖掉前面加载的
数据持久
修改conf/application.properties文件,增加支持mysql数据源配置(目前只支持mysql),添加mysql数据源的url、用户名和密码。
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://11.162.196.16:3306/nacos_devtest?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=nacos_devtest
db.password=youdontknow
初始化mysql数据库,数据库初始化文件:nacos-mysql.sql
常用表格说明
- config_info:存储配置文件信息 xx.yml
- his_config_info:保存配置文件的修改记录 历史信息
- users: 登录用户信息
- tenant_info: namespace信息
集群
通过Nginx进行请求转发
在nacos的解压目录nacos/的conf目录下,有配置文件cluster.conf,请每行配置成ip:port。(请配置3个或3个以上节点)
# ip:port
127.0.0.1:13333
127.0.0.1:14444
127.0.0.1:15555
启动
./startup.sh -p 13333
./startup.sh -p 14444
./startup.sh -p 15555
通过-p指定端口
配置nginx
nacos.conf
upstream cluster{
server 127.0.0.1:13333;
server 127.0.0.1:14444;
server 127.0.0.1:15555;
}
server{
listen 11111;
server_name localhost;
location / {
proxy_pass http://cluster;
}
}
启动nginx
集群已经搭建好了
访问
localhost:11111/nacos
然后在项目中配置
spring:
application:
name: nacos-config-client-load
cloud:
nacos:
config:
server-addr: 127.0.0.1:11111
file-extension: yml
server:
port: 8056
Sentinel
注意:启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。
- Windows平台安装包下载
可以从https://github.com/alibaba/Sentinel/releases
下载sentinel-dashboard-$version.jar
包。
使用如下命令启动控制台:
java -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -Dcsp.sentinel.api.port=8719 -jar D:\sentinel\sentinel-dashboard-1.8.0.jar
1
其中-Dserver.port=8718
用于指定Sentinel
控制台端口为8718
,F:\software\sentinel\sentinel-dashboard-1.8.0.jar
为下载的包路径地址。
打开控制台
Sentinel
提供了一个可视化的操作平台,安装好之后,在浏览器中输入(http://localhost:8718 (opens new window))就可以访问了,默认的用户名和密码都是sentinel
(我使用的是1.8.0版本)
懒加载的只有当有流量访问的时候才会工作
连接
添加依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
配置
server:
port: 18080
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
datasource:
ds1:
file:
file: classpath:flowrule.json
data-type: json
rule-type: flow
ds2:
nacos:
server-addr: localhost:8848
dataId: sentinel-core-example
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
application:
name: sentinel-core-example
限流
方式一 根据URL限流
@RestController
public class DemoController {
// 设置阈值为1 每秒只能访问1次
//流量多的时候会报错Blocked by Sentinel(flow limiting)
@GetMapping("/hello")
public String hello() {
return "hello sentinel";
}
}
对hello请求进行限流
自定义降级策略
public class DemoUrlBlockHandler implements UrlBlockHandler {
@Override
public void blocked(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws IOException {
httpServletResponse.getWriter().println("error url");
}
}
配置类
通过配置类进行绑定
@Configuration
public class SentinelConfig {
@PostConstruct
public void init() {
WebCallbackManager.setUrlBlockHandler(new DemoUrlBlockHandler());
WebCallbackManager.setRequestOriginParser(new IpRequestOriginParser());
}
}
方式二 通过资源名限流
resource下面挂了一个resource资源 对资源进行限流
/*
@GetMapping("/resource")
//通过@SentinelResource指定资源名
@SentinelResource("resource") //需指定具体的资源 否则会报错500
public String resource() {
return "hello resource";
}
*/
// 方式一
@GetMapping("/resource")
@SentinelResource(value = "resource", blockHandler = "exHandler") //默认找本类下的方法
public String resource() {
return "hello resource";
}
public String exHandler(BlockException ex) {
return "exHandeler error";
}
// 方式二 通过blockHandlerClass指定类 通过blockHandler指定方法
@GetMapping("/resource1")
@SentinelResource(value = "resource1", blockHandler = "exHandler", blockHandlerClass = {ExceptionUtil.class})
public String resource1() {
return "hello resource";
}
处理异常的类
public class ExceptionUtil {
public static String exHandler(BlockException ex) {
return "exHandler error";
}
}
黑白名单控制
配置类
@Configuration
public class SentinelConfig {
@PostConstruct
public void init() {
WebCallbackManager.setUrlBlockHandler(new DemoUrlBlockHandler());
WebCallbackManager.setRequestOriginParser(new IpRequestOriginParser());//定义判断标准是什么
}
}
public class IpRequestOriginParser implements RequestOriginParser {
/** 根据IP
* Parse the origin from given HTTP request.
*
* @param request HTTP request
* @return parsed origin
*/
@Override
public String parseOrigin(HttpServletRequest request) {
return request.getRemoteAddr(); //生产上不要这么使用
}
}
接口
@RestController
public class SecurityController {
@GetMapping("/white")
public String white() {
return "hello white";
}
@GetMapping("/black")
public String black() {
return "hello black";
}
}
再sentinel面板中的授权规则进行设置
不符合规则的会触发降级操作
热点限流
按照不同的参数进行划分
@RestController
public class ParamController {
@GetMapping("/param")
@SentinelResource(value="/param",blockHandler = "exHandler")
public String param(String type) {
return "success";
}
public String exHandler(String type, BlockException ex) {
return "exHandler error";
}
}
热点限流只对resource生效,对普通的请求路径是不生效的,因此要使用热点限流的功能一定要使用@SentinelResource功能进行标注
在sentinel面板中的簇点链路中的/param请求下的param资源进行热点操作
其中参数索引以0开始,type参数的参数索引为0
当不带参数的时候进行访问,一切正常
带param参数访问的时候,会触发降级,执行降级策略。带其他的参数也不会触发降级
自适应限流
超过阈值进行处理,所有请求服务挂起block掉,不超过不进行处理
在sentinel控制台系统规则面板进行设置。新增系统规则
阈值类型
- LOAD:瞬间处理的进程数,一般设置为CPU个数*0.7
- RT:服务的平均响应时间,单位为毫秒。超过指定时间的服务都被挂起
- 线程数:
- 入口QPS:
- CPU使用率:0.7
规则持久化
重启应用后我们设置的规则就没了。
目前支持file,nacos,zk,apollo,redis这五种类型
file
在resource文件夹设置规则
flowrule.json
[
{
"resource": "hello",
"count": 1,
"grade": 1,
"limitApp": "default",
"strategy": 0,
"controlBehavior": 0
}
]
一条限流规则主要由下面的几个因素构成,我们可以组成这些元素来实现不同的限流效果
- resource:资源名,即限流规则的作用对象
- count:限流阈值
- grade:限流阈值类型(QPS或并发线程数)1:QPS 0:线程数
- limitApp:流控针对的调用来源,若为default则不区分调用来源
- strategy:调用关系限流策略。接口是链路的一直往后调用,是否整个链路都限流
- controlBehavior:流量控制效果(直接拒绝、WarmUP、均速排队)
配置
server:
port: 18080
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
datasource:
ds1:
file:
file: classpath:flowrule.json
data-type: json
rule-type: flow
application:
name: sentinel-core-example
Nacos
添加依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
<version>1.7.0</version>
</dependency>
配置
server:
port: 18080
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8080
datasource:
ds2:
nacos:
server-addr: localhost:8848
dataId: sentinel-core-example
groupId: DEFAULT_GROUP
data-type: json
rule-type: flow
application:
name: sentinel-core-example
整合Feign
https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
提供方
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
@RestController
public class DemoController {
@GetMapping("/feign")
public String feign() {
return "hello sentinel feign";
}
}
配置
server:
port: 18082
spring:
application:
name: sentinel-feign-provider
cloud:
nacos:
server-addr: localhost:8848
消费方
@RestController
public class DemoController {
@Autowired
private DemoFeignClient feignClient;
@GetMapping("/hello")
public String hello() {
return feignClient.feign();
}
}
@Component
public class DemoFeginClientFallback implements DemoFeignClient {
@Override
public String feign() {
return "error";
}
}
@FeignClient(value = "sentinel-feign-provider", fallback = DemoFeginClientFallback.class)
public interface DemoFeignClient {
@GetMapping("/feign")
String feign();
}
server:
port: 18081
spring:
application:
name: sentinel-feign-comsumer
cloud:
nacos:
server-addr: localhost:8848
@EnableFeignClients
@SpringCloudApplication
public class SentinelFeignProvierApplication {
public static void main(String[] args) {
SpringApplication.run(SentinelFeignProvierApplication.class, args);
}
}
整合gateway
GatewayFlowRule
:网关限流规则,针对 API Gateway 的场景定制的限流规则,可以针对不同 route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的限流。ApiDefinition
:用户自定义的 API 定义分组,可以看做是一些 URL 匹配的组合。比如我们可以定义一个 API 叫my_api
,请求 path 模式为/foo/**
和/baz/**
的都归到my_api
这个 API 分组下面。限流的时候可以针对这个自定义的 API 分组维度进行限流。
Seata分布式事务
Seata是阿里开源的一个分布式事务框架。 Seata主要有两种分布式事务实现方案,AT及TCC
- AT模式主要关注多 DB 访问的数据一致性,当然也包括多服务下的多 DB 数据访问一致性问题
- TCC 模式主要关注业务拆分,在按照业务横向扩展资源时,解决微服务间调用的一致性问题
下载seata-server并运行,下载地址
每个服务加上seata的依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-seata</artifactId> <version>2.1.1.RELEASE</version> </dependency>
- 加上file.conf,并修改service的vgroup
- 指明配置中心—–加上registry.conf配置
数据库导入表