springcloud记录篇9-springcloud孵化器项目Spring Cloud Alibaba

一。 Spring Cloud Alibaba介绍

spring Cloud Alibaba 致力于提供分布式应用服务开发的一站式解决方案。此项目包含开发分布式应用服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。

依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接入阿里分布式应用解决方案,通过阿里中间件来迅速搭建分布式应用系统。

主要功能

  • 服务限流降级:默认支持为 HTTP 服务的提供限流保护,也支持添加注解实现方法的自定义限流降级,且支持动态修改限流降级规则。
  • 服务注册与发现:适配 sprig cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
  • 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
  • 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。

组件:

Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

AliCloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。

二。Nacos使用示例

Nacos用于实现注册中心和配置中心
github源码 :https://github.com/alibaba/Nacos
官方文档:https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html

1。安装nacos服务器

下载地址 zip包

解压 因为nacos默认的配置数据存储在derby文件数据库中(启动生成 data\derby-data数据),防止文件损坏(一般要求配置数据并需永久保存安全服务器,比如 mysql主从库中,注册信息 重启丢失了 注册服务器自动重连) |
所以 nacos提供了数据库的存储方式
参考自 https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html
假设本机安装了 mysql数据库  (mysql最好事先设计好主从 否则数据库挂了 就无法使用nacos)

连接数据 执行 conf/nacos-mysql.sql  创建数据库 nacos_config 

修改conf/application.properties 将后面db相关的配置打开 (放弃了 怎么配置都不写到数据库。。。还是先derby 官网文档渣渣  只能有时间分析源码了)

db.num=1
db.url.0=jdbc:mysql://localhost:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=nacos_devtest
db.password=youdontknow

启动nacos-server  点击 bin/startup.cmd
配置集群  起多个nacos-server 将每一台配置(懒得试了):

    在nacos的解压目录nacos/的conf目录下,有配置文件cluster.conf,请每行配置成ip:port。

window安装curl https://curl.haxx.se/download.html  linux直接使用
使用rest测试配置参数和获取参数

curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=example&group=DEFAULT_GROUP&content=useLocalCache=true"

获取参数:

C:\Users\Administrator>curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=example&group=DEFAULT_GROUP"
useLocalCache=true


2。使用springcloud获取配置数据

理解几个概念 dataid可以理解是一个springcloud配置中心文件的意思

在 Nacos Spring Cloud 中,dataId 的完整格式如下:

${prefix}-${spring.profile.active}.${file-extension}
  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix来配置。
  • spring.profile.active【注意这里是profiles 文档求规范 即为当前环境对应的 profile,详情可以参考 Spring Boot文档。 __注意:当 __spring.profile.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式变成 ${prefix}.${file-extension}
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置。目前只支持 properties 类型。

创建springboot项目 添加依赖

<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>cn.ps</groupId>
  <artifactId>CLOUD_PUBLIC</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.6.RELEASE</version>
	</parent>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
	
		<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-config</artifactId>
	</dependency>
		<dependency>
		    <groupId>org.springframework.cloud</groupId>
		    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
		</dependency>
		
		
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Finchley.SR1</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-alibaba</artifactId>
				<version>0.2.0.BUILD-SNAPSHOT</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>

	</dependencyManagement>
	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/libs-snapshot-local</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
			<releases>
				<enabled>false</enabled>
			</releases>
		</repository>
	</repositories>
</project>

bootstrap.properties

spring.cloud.nacos.config.server-addr=127.0.0.1:8848

application.properties

spring.application.name=example
spring.profiles.active=dev
spring.cloud.nacos.config.file-extension=properties

添加main测试类

package cn.ps;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TestConf {

	
	public static void main(String[] args) throws Exception {
		SpringApplication.run(TestConf.class, args);
	}

}

添加控制层:

package cn.ps;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {

    @Value("${useLocalCache:false}")
    private boolean useLocalCache;

    @RequestMapping("/get")
    public boolean get() {
        return useLocalCache;
    }
}

使用cput添加一个配置数据

curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=example-dev.properties&group=DEFAULT_GROUP&content=useLocalCache=true"

浏览器访问路径测试
http://localhost:8080/config/get
发现输出结果为true
再次修改结果查看是否自动重载

2。使用springcloud配置注册和发现

新建一个生产者项目  注册到nacos-server 添加maven

<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>cn.ps</groupId>
	<artifactId>CLOUD_PUBLIC</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.6.RELEASE</version>
	</parent>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>Finchley.SR1</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-alibaba</artifactId>
				<version>0.2.0.BUILD-SNAPSHOT</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>

	</dependencyManagement>
	<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/libs-snapshot-local</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
			<releases>
				<enabled>false</enabled>
			</releases>
		</repository>
	</repositories>
</project>

添加main方法

package cn.ps;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class TestPub {

	
	public static void main(String[] args) throws Exception {
		SpringApplication.run(TestPub.class, args);
	}

}

添加控制层类 将来调用

package cn.ps;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @RequestMapping("/hello")
    public String get() {
        return "hello";
    }
}

 

三。 Sentinel使用示例

sentinel完成 Spring Cloud 应用的限流管理
sentinel示例 参考 https://github.com/spring-cloud-incubator/spring-cloud-alibaba/blob/master/spring-cloud-alibaba-examples/sentinel-example/sentinel-core-example/readme-zh.md

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Sentinel 具有以下特征:

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。
  • 完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

Sentinel 的主要特性:

Sentinel 分为两个部分:

  • 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
  • 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。

1。安装dashboard控制台

下载sentinel控制台jar包 参考 https://github.com/alibaba/Sentinel/wiki/%E6%8E%A7%E5%88%B6%E5%8F%B0
下载的1.4.1版本 

下载jar包在某个目录后,启动该jar包

java -Dserver.port=8883 -Dcsp.sentinel.dashboard.server=localhost:8883 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.4.1.jar

启动后访问:http://localhost:8883 界面如下:

如果我们的程序连接上控制台,并且设置了, 左边菜单栏就会显示对应的限流项目的应用名称(spring.application.name)可以对程序进行限流控制


2。编写熔断或者降级程序

使用springboot和springcloud集成 参考wiki章节:主流框架的适配#spring-cloud。
https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E6%B5%81%E6%A1%86%E6%9E%B6%E7%9A%84%E9%80%82%E9%85%8D#spring-cloud

参考文档 
https://github.com/spring-cloud-incubator/spring-cloud-alibaba/wiki/Sentinel

添加依赖

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

如果依赖无法加载,添加spring的snapshot仓库

<repositories>
		<repository>
			<id>spring-snapshots</id>
			<name>Spring Snapshots</name>
			<url>https://repo.spring.io/libs-snapshot-local</url>
			<snapshots>
				<enabled>true</enabled>
			</snapshots>
			<releases>
				<enabled>false</enabled>
			</releases>
		</repository>
	</repositories>

如果你的应用是spring或者springmvc的环境 必须配置aspectj的环绕类,这个限流和降级的原理就是使用aop实现的
springcloud的程序控制层不需要添加该bean,如果是service层其他层的限流必须添加该bean否则无效

@Configuration
public class SentinelAspectConfiguration {

    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}

可以打开SentinelResourceAspect这个类

application.properties内容:

management.endpoints.web.exposure.include=*
spring.application.name=sentinelexample
server.port=8882
spring.cloud.sentinel.transport.dashboard=localhost:8883 #连接sentinel控制台的ip和端口

1》熔断规则实现

Sentinel 以流量(qps[每秒的请求数],thread[最大线程数])为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

熔断:如果流量达到某个设置的限度,调用方抛出一个错误信息(BlockException),调用方接受错误后处理,一般该功能无法使用,前端加载出错等异常。
降级:如果流量达到某个设置的限度,调用方调用其他的方法返回数据(并不是错误),主不达求其次。

1》》控制层的web请求熔断

添加一个控制层的方法(sentinel会将每个路径自动添加到资源集合中 ,资源的名字就是路径 /test1)假设端口是8882

@GetMapping("/test1")
public String test1(){
		return "test1";
}

 给资源添加流量限制规则:首先设置一个资源规则到sentinel dashboard控制台

@GetMapping("/setTest1FlowRule")
	public String setRule(){
		List<FlowRule> rules = new ArrayList<FlowRule>();//限流规则列表
		FlowRule rule = new FlowRule(); //创建一个规则
		rule.setResource("/test1"); //设置需要定义规则的名称
		// set limit qps to 10
		rule.setCount(1);//设置每秒的qps数量,为了演示效果使用1
		rule.setGrade(RuleConstant.FLOW_GRADE_QPS);//限制qps
		rule.setLimitApp("default"); //设置允许的请求的来源默认 default允许所有请求过来
		rules.add(rule);//添加到集合中	
		FlowRuleManager.loadRules(rules);//静态方法添加到sentinel控制台
		//自定义控制层限流规则达到阀值后 自动出现错误  以下是自定义输出错误
		WebCallbackManager.setUrlBlockHandler(new UrlBlockHandler() {
			@Override
			public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws IOException {
				response.getWriter().print("<font color=red>error"+ex.toString()+"</font>");
			}
		});
		return "1";
	}

在浏览器上执行这个设置规则的路径 http://localhost:8082/setTest1FlowRule  回到sentinel控制台,查看是否有当前项目的监控项
出现

接下来访问 http://localhost:8082/test1
如果qps没有超过1 显示:test1 如果超过了就会自动进入UrlBlockHandler显示红色error和异常

2》其他层(service或者repository或则其他方法)的调用熔断

 比如在控制层调用service层方法

@Autowired
	private TestServiceImpl tsi;
	@GetMapping("/test2")
	public String test2(){
		return tsi.getText();
	}

TestServiceImpl内容:

@Service
public class TestServiceImpl {
    //指定资源名称,熔断后调用的方法
	@SentinelResource(value="text1",entryType=EntryType.IN,blockHandler = "exceptionHandler") //出现熔断后调用方法
	public String getText() {
		return "测试文本";
	}

    // Block 异常处理函数,参数最后多一个 BlockException,其余与原函数一致.
    public String exceptionHandler( BlockException ex) {
        return "block" ;
    }
}

设置限流规则,注意资源名称是text1 

@GetMapping("/setTest1FlowRule")
	public String setRule(){
		List<FlowRule> rules = new ArrayList<FlowRule>();
		FlowRule rule1 = new FlowRule();
		rule1.setResource("text1");
		// set limit qps to 10
		rule1.setCount(1);
		rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
		rule1.setLimitApp("default");
		rules.add(rule1);
		
		FlowRuleManager.loadRules(rules);
		return "1";
	}

使用浏览器 访问 http://localhost:8082/test2就会调用getText哪个text1资源方法,qps没有到达显示:测试文本,否则显示block

其他关于降级使用DegradeRule,系统规则使用SystemRule,权限规则使用AuthorityRule 具体参考官网
https://github.com/spring-cloud-incubator/spring-cloud-alibaba/wiki/Sentinel

 

 

 

 

 

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值