SpringCloud-Alibaba入门
遇到的问题
start from 2021年12月16日04:30:01
1)P58-9:53,spring.cloud.nacos.discovery.service=${spring.application.name}。13:00,回顾服务间的通信。32:00,服务发现的客户端。 2)P59-20:00,在nacos配置中心配置configclient-prod.properties,将自身配置交给远端nacos-config进行管理。 3)P61-37:00,新建一个名为nacos的mysql数据库。
SpringCloud 组件
- 服务注册与发现组件:eureka、consul =》
nacos - 服务间通信组件:RestTemplate+ribbon,Openfeign =》
restTemplate+ribbon,Openfeign
服务间的通信有两种方式:1.Http Rest(推荐) 2.RPC。使用Rest方式实现服务间通信:①使用spring框架为我们提供的RestTemplate,但没法实现负载均衡。②RestTemplate+Ribbon,可以实现负载均衡,但地址耦合严重。所以更推荐使用 ③OpenFeign方式调用。
- 服务降级和熔断:hystrix、hystrix dashboard =》
sentinel - 服务网关组件:zuul1.x/zuul2.x、gateway =》
gateway - 统一配置中心组件,消息总线组件:config+bus自动配置刷新 =》
nacos
SpringCloud-Alibaba 特点
- a.服务注册中心,服务配置中心:
nacos====> 替换 eureka consul 替换config+bus - b.服务熔断、流控:
sentinel(sentinel、sentinel dashBoard)====> 替换原始的Hystrix(Hystrix Hystrix DashBoard) - c.分布式配置& 事件驱动消息总线:
nacos替换 config & bus - d.分布式事务&dubbo:
seta
父项目中依赖维护
<groupId>com.jun</groupId>
<artifactId>springcloudalibaba_parent</artifactId>
<version>1.0</version>
<!--继承springboot父项目-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<!--定义版本号-->
<properties>
<spring.cloud.version>Hoxton.SR6</spring.cloud.version>
<spring.cloud.alibaba.version>2.2.1.RELEASE</spring.cloud.alibaba.version>
</properties>
<!--维护依赖-->
<dependencyManagement>
<dependencies>
<!--维护springcloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--维护springcloud-alibaba-->
<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>
</dependencies>
</dependencyManagement>
1.Nacos组件入门
- Name Service(服务注册与发现) & Configurations Services(统一配置中心)
- 默认监听web端口:8848
在Linux环境下安装nacos
查看java的安装路径:
[root@rabbitmq ~]# find / -name java
添加jdk1.8的环境变量(之前已经配好了),在最末尾处加上下面两句:
export JAVA_HOME=/usr/java/jdk/jdk1.8.0_161
export PATH=$PATH:$JAVA_HOME/bin
[root@rabbitmq ~]# vim /etc/profile
重新加载生效:
[root@rabbitmq ~]# source /etc/profile
1.解压缩nacos的安装包
[root@rabbitmq ~]# cd /root/nacos/
[root@rabbitmq nacos]# ll
总用量 73056
-rw-r--r--. 1 root root 74805643 12月 16 14:20 nacos-server-1.3.1.tar.gz
[root@rabbitmq nacos]# tar -zxvf nacos-server-1.3.1.tar.gz
2.启动nacos服务:打开终端进入nacos的bin目录执行:【注意】默认nacos启动是以集群模式启动的,必须满足多个节点。
[root@rabbitmq nacos]# cd nacos/bin
[root@rabbitmq bin]# ./startup.sh -m standalone
3.查看日志:是否启动成功
[root@rabbitmq bin]# tail -f /root/nacos/nacos/logs/nacos.log
4.访问nacosweb地址:http://192.168.200.130:8848/nacos 【注意】访问前,关闭防火墙。默认的登录密码都是nacos
scalibaba01_nacosclient
pom.xml
- 使用nacos作为注册中心之后,不需要引入健康检查actuator依赖了。关闭立即移除服务,和consul一样没有自我保护机制。
<parent>
<artifactId>springcloudalibaba_parent</artifactId>
<groupId>com.jun</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>scalibaba01_nacosclient</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--引入nacos-client的依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
application.properties
server.port=8989
spring.application.name=NACOSCLIENT
# nacos-server的总地址
spring.cloud.nacos.server-addr=192.168.200.130:8848
# 作为nacos-client注册地址 (可以不写)
spring.cloud.nacos.discovery.server-addr=${spring.cloud.nacos.server-addr}
启动类
@SpringBootApplication
@EnableDiscoveryClient //开启服务的注册,不加这个注解也行。
public class NacosClientApplication {}
服务间通信
scalibaba02_users
pom.xml
<parent>
<artifactId>springcloudalibaba_parent</artifactId>
<groupId>com.jun</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>scalibaba02_users</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos-client-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--引入openfeign的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
application.properites
server.port=8989
spring.application.name=USERS
spring.cloud.nacos.server-addr=192.168.200.130:8848
#----------------
server.port=9090
spring.application.name=PRODUCTS
spring.cloud.nacos.server-addr=192.168.200.130:8848
启动类
@SpringBootApplication
@EnableFeignClients //开启openfeign调用支持
public class UsersApplication {}
//---------------------
@SpringBootApplication
public class ProductsApplication {}
ProductController
@RestController
public class ProductController {
private static final Logger log = LoggerFactory.getLogger(ProductController.class);
@Value("${server.port}")
private int port;
@GetMapping("/product")
public String product(Integer id){
log.info("id: {}",id);
return "商品服务返回: "+id+",当前提供服务端口为: "+port;
}
}
UserController
//com.jun.config
@Configuration
public class BeansConfig {
@Bean
@LoadBalanced //负载均衡客户端
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
//com.jun.controller
@RestController
public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
@Autowired
private DiscoveryClient discoveryClient;//服务发现客户端
@Autowired
private LoadBalancerClient loadBalancerClient; //负载均衡客户端组件
@Autowired
private RestTemplate restTemplate; //这个对象才是具有负载均衡restTemplate
@Autowired
private ProductClient productClient; //使用OpenFeign的方式实现通信
//推荐http rest方式通信:
@GetMapping("/invoke")
public String invokeProduct(){
log.info("调用用户服务....");
//return "调用用户服务成功!";
//1.restTemplate调用商品服务,缺点: 1.无法实现请求负载均衡。2.路径写死代码中不利于后续维护
/*String result = new RestTemplate()
.getForObject("http://localhost:9090/product?id=21", String.class);
log.info("商品服务调用结果:{}",result);
return result;*/
//2.discoveryClient使用ribbon组件实现负载均衡
// 1.引入ribbon依赖(nacos-client中存在这个依赖)。2.使用ribbon完成负载均衡
// DiscoveryClient LoadBalanceClient @LoadBalance
/*List<ServiceInstance> serviceInstances = discoveryClient.getInstances("PRODUCTS");
for (ServiceInstance serviceInstance : serviceInstances) {
log.info("服务主机:{} 服务端口:{} 服务uri:{}",serviceInstance.getHost()
,serviceInstance.getPort(),serviceInstance.getUri());
}
String result =new RestTemplate().getForObject(serviceInstances.get(0).getUri() +
"/product?id=21",String.class); //
log.info("商品服务调用结果: {}",result);
return result;*/
//2.loadbalanceClient
/*ServiceInstance serviceInstance = loadBalancerClient.choose("PRODUCTS"); //已经进行负载均衡之后返回节点:轮询
String result =new RestTemplate().getForObject(serviceInstance.getUri() +
"/product?id=21",String.class);
log.info("商品服务调用结果: {}",result);
return result;*/
//3.@LoadBalance注解
/*String result = this.restTemplate.getForObject("http://PRODUCTS/product?id=21", String.class);
log.info("商品服务调用结果: {}",result);
return result;*/
//4.使用OpenFeign的方式
String result = productClient.product(40);
log.info("商品服务调用结果: {}",result);
return result;
}
}
//com.jun.feignclients
@FeignClient("PRODUCTS")
public interface ProductClient {
@GetMapping("/product")
String product(@RequestParam("id") Integer id);
}
Nacos统一配置中心的使用
- nacos作为统一配置中心:它管理配置文件的方式是在自己所在的服务器上形成一个版本库,因此不需要再创建远程版本库。
scalibaba04_configclient
<parent>
<artifactId>springcloudalibaba_parent</artifactId>
<groupId>com.jun</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>scalibaba04_configclient</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--引入配置中心依赖,表示要从nacos上获取配置,项目中不再写application.properties-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
bootstrap.properties
#server.port=8888
#spring.application.name=CONFIGCLIENT
#spring.cloud.nacos.server-addr=192.168.200.130:8848
#customer.username=junhr
# 上述配置信息已在nacos配置中心配置好了,以后启动应用自动从nacos上拉取
# 3.将配置放到EMS组里:
spring.cloud.nacos.server-addr=192.168.200.130:8848
#指明命名空间的id
spring.cloud.nacos.config.namespace=afd8acc3-2e14-4eda-aced-1cd88ba55b9e
spring.cloud.nacos.config.group=CONFIGCLIENT
spring.cloud.nacos.config.name=configclient-dev
spring.cloud.nacos.config.file-extension=properties
# 指明config-server的地址
# spring.cloud.nacos.config.server-addr=192.168.200.130:8848
# 指明从哪个组进行配置的获取
# spring.cloud.nacos.config.group=DEFAULT_GROUP
# 2.第二种获取配置文件的方式:dataId = prefix + env + file-extension
# spring.cloud.nacos.config.prefix=configclient
# spring.profiles.active=dev
# spring.cloud.nacos.config.file-extension=properties
# 1.第一种获取配置文件的方式:dataId = name + file-extension
# 指明拉取指定组的哪个文件
# spring.cloud.nacos.config.name=configclient-prod
# 拉取这个配置哪个后缀的配置文件
# spring.cloud.nacos.config.file-extension=properties
DemoController.java
@SpringBootApplication
public class ConfigClientApplication {} //启动类
//--------------
@RestController
@RefreshScope //允许远端配置修改自动刷新
public class DemoController {
private static final Logger log = LoggerFactory.getLogger(DemoController.class);
@Value("${customer.username}")
private String username;
@GetMapping("/demo")
public String demo(){
log.info("demo ok !!!");
return "demo ok !!! username:"+ username;
}
}
将Nacos中的数据持久化到MySQL中
- 默认nacos存在配置信息持久化,默认的持久化方式为内嵌数据库derby。缺点是无法友好的展示数据。官方建议:在生产情况下推荐将配置存入mysql数据库(版本要求在5.6.5+)。
1.查看mysql是否安装
[root@rabbitmq ~]# systemctl status mysqld
Unit mysqld.service could not be found.
2.添加官方的yum源创建并编辑mysql-community.repo文件
[root@rabbitmq ~]# vi /etc/yum.repos.d/mysql-community.repo
3.粘贴以下内容到源文件中:
[mysql57-community]
name=MySQL 5.7 Community Server
baseurl=http://repo.mysql.com/yum/mysql-5.7-community/el/7/$basearch/
enabled=1
gpgcheck=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql
4.安装mysql
[root@rabbitmq ~]# yum install mysql-community-server -y
5.启动mysql数据库:
[root@rabbitmq ~]# systemctl start mysqld
6.获取临时密码:grep 'temporary password' /var/log/mysqld.log 得到的临时密码:cpp*Qu=rI327
7.修改密码:mysqladmin -u root -p password 回车 输入原始密码 再输入新的密码(Root!Q2w)
8.登录mysql:mysql -u root -p 回车后输入密码
9.开启mysql远程连接权限(登录之后)
grant all privileges on *.* to 'root'@'%' identified by 'Root!Q2w' with grant option;
10.刷新权限:flush privileges;
- 如果想要让nacos数据持久化到mysql数据库,需要先创建一个数据库,如:utf-8编码的数据库nacos。②在nacos库中执行nacos-mysql.sql。③修改nacos配置文件持久化信息到mysql库中:
vim application.properties
Nacos-server集群搭建
- P62-16:32,拷贝三份nacos。31:00,测试是否启动成功。
[root@rabbitmq ~]# ls
anaconda-ks.cfg Hello.java java nacos nginx rabbitmq shcode zookeeper
[root@rabbitmq ~]# cd /root/nacos/nacos
[root@rabbitmq nacos]# ls
bin conf data LICENSE logs NOTICE target
搭建nacos之前,先把nacos下打data数据清除掉
[root@rabbitmq nacos]# rm -rf /root/nacos/nacos/data/
拷贝三份nacos节点:
[root@rabbitmq ~]# cp -r /root/nacos/nacos nacos01
[root@rabbitmq ~]# cp -r /root/nacos/nacos nacos02
[root@rabbitmq ~]# cp -r /root/nacos/nacos nacos03
[root@rabbitmq ~]# ll
总用量 8
-rw-------. 1 root root 1259 11月 18 23:19 anaconda-ks.cfg
-rw-r--r--. 1 root root 113 11月 19 03:49 Hello.java
drwxr-xr-x. 2 root root 41 12月 11 16:33 java
drwxr-xr-x. 3 root root 52 12月 16 14:29 nacos
drwxr-xr-x. 6 root root 84 12月 17 01:14 nacos01
drwxr-xr-x. 6 root root 84 12月 17 01:14 nacos02
drwxr-xr-x. 6 root root 84 12月 17 01:14 nacos03
【注意】先关闭防火墙
[root@rabbitmq ~]# systemctl stop firewalld
更改conf中的集群搭建配置文件名:
[root@rabbitmq ~]# mv nacos01/conf/cluster.conf.example nacos01/conf/cluster.conf
[root@rabbitmq ~]# mv nacos02/conf/cluster.conf.example nacos02/conf/cluster.conf
[root@rabbitmq ~]# mv nacos03/conf/cluster.conf.example nacos03/conf/cluster.conf
[root@rabbitmq ~]# ls nacos01/conf
application.properties application.properties.example cluster.conf nacos-logback.xml nacos-mysql.sql schema.sql
在nacos01的conf配置文件中添加:【nacos2.0版本端口至少间隔一个,否则启动端口会占用报错】
[root@rabbitmq ~]# vim nacos01/conf/cluster.conf
[root@rabbitmq ~]# cat nacos01/conf/cluster.conf
192.168.200.130:8845
192.168.200.130:8846
192.168.200.130:8847
将nacos01中的集群配置文件覆盖到nacos02和nacos03中
[root@rabbitmq ~]# cp nacos01/conf/cluster.conf nacos02/conf/cluster.conf
cp:是否覆盖"nacos02/conf/cluster.conf"? y
[root@rabbitmq ~]# cp nacos01/conf/cluster.conf nacos03/conf/cluster.conf
cp:是否覆盖"nacos03/conf/cluster.conf"? y
[root@rabbitmq ~]# cat nacos02/conf/cluster.conf
192.168.200.130:8845
192.168.200.130:8846
192.168.200.130:8847
修改nacos各自的端口号为:8845,8846,8847
[root@rabbitmq ~]# vim nacos01/conf/application.properties
[root@rabbitmq ~]# vim nacos02/conf/application.properties
[root@rabbitmq ~]# vim nacos03/conf/application.properties
分别启动三台机器
[root@rabbitmq ~]# ./nacos01/bin/startup.sh
[root@rabbitmq ~]# ./nacos02/bin/startup.sh
[root@rabbitmq ~]# ./nacos03/bin/startup.sh
启动时可以分别观察日志:
[root@rabbitmq ~]# tail -f nacos01/logs/nacos.log
如果能正常启动的话:输入jps命令可以查看到进程信息。
启动成功后,分别在浏览器中登录nacos,如:http://192.168.200.130:8845/nacos
Nginx实现nacos高可用
- P63-6:14,希望使用Nginx的代理服务器功能。(反向代理)
1.安装必要的gcc依赖【在没有安装gcc的情况下】:yum install -y gcc pcre-devel zlib-devel
2.解压缩上传到Linux上的Nginx:
[root@rabbitmq ~]# ls
logs nacos nacos01 nacos02 nacos03 nginx rabbitmq zookeeper
[root@rabbitmq ~]# cd nginx
[root@rabbitmq nginx]# ls
nginx-1.11.1.tar.gz
[root@rabbitmq nginx]# tar -zxvf nginx-1.11.1.tar.gz
3.查看Nginx安装目录:
[root@rabbitmq nginx]# ls
nginx-1.11.1 nginx-1.11.1.tar.gz
[root@rabbitmq nginx]# cd nginx-1.11.1
[root@rabbitmq nginx-1.11.1]# ls
auto CHANGES CHANGES.ru conf configure contrib html LICENSE man README src
4.在Nginx安装目录中执行如下命令:(指定安装位置):./configure --prefix=/usr/nginx
[root@rabbitmq nginx-1.11.1]# ./configure --prefix=/usr/nginx
5.执行上述命令成功后,执行如下命令编译并安装:make && make install
[root@rabbitmq nginx-1.11.1]# make && make install
6.在usr目录下是否安装成功:
[root@rabbitmq nginx-1.11.1]# ls /usr/
bin etc games include java lib lib64 libexec local nginx sbin share src tmp tomcat zookeeper-cluster
[root@rabbitmq nginx-1.11.1]# cd /usr/nginx/
[root@rabbitmq nginx]# ls
conf html logs sbin
7.启动:进入sbin目录:./nginx
8.查看Nginx是否启动成功(Nginx不是java的进程,aux代表前台的所有进程):ps aux|grep nginx
[root@rabbitmq nginx]# cd sbin/
[root@rabbitmq sbin]# ls
nginx
[root@rabbitmq sbin]# ./nginx
[root@rabbitmq sbin]# ps aux|grep nginx
root 12039 0.0 0.0 20520 600 ? Ss 02:16 0:00 nginx: master process ./nginx
nobody 12040 0.0 0.0 20948 1288 ? S 02:16 0:00 nginx: worker process
root 12042 0.0 0.0 112824 976 pts/0 R+ 02:17 0:00 grep --color=auto nginx
【注意】Nginx默认监听的端口是:80端口。访问:http://192.168.200.130:80
9.(反向代理Nginx),首先关闭Nginx服务:./nginx -s stop 或者使用kill命令杀死master进程
[root@rabbitmq sbin]# ./nginx -s stop
[root@rabbitmq sbin]# ps aux|grep nginx
root 12047 0.0 0.0 112824 980 pts/0 R+ 02:22 0:00 grep --color=auto nginx
10.修改Nginx的conf配置文件
[root@rabbitmq sbin]# cd ../
[root@rabbitmq nginx]# ls
#启动后会生成一些临时目录
client_body_temp conf fastcgi_temp html logs proxy_temp sbin scgi_temp uwsgi_temp
[root@rabbitmq nginx]# cd conf/
[root@rabbitmq conf]# vim nginx.conf
a.加入如下配置: (upstream后面的名字随意取,在{}写Nginx需要管理的所有节点)
upstream nacos-servers {
server 192.168.200.130:8845;
server 192.168.200.130:8846;
server 192.168.200.130:8847;
}
b.为了再输入http://192.168.200.130:80时,不再希望Nginx主页处理,
而是转发到nacos-server中的某个节点如8845处理。P63-10:26
location / {
proxy_pass http://nacos-servers/;
}
11.加载配置启动:./nginx -c /usr/nginx/conf/nginx.conf
12.在浏览器中输入:192.168.200.130/nacos 会通过负载均衡在nacos的8845,8846,8847节点中选择一个连接。
之后在项目的配置文件中只需要写:spring.cloud.nacos.server-addr=192.168.200.130:80(之后项目中这里写的
是一个域名,用域名去映射Nginx的地址) 就能实现nacos的高可用。
2.sentinal哨兵组件
- P64-27:00,Sentinal-dashboard的讲解。P66-23:53,关于系统吞吐量相关的概念,QPS。P66-42:00,新增流控规则。
P67-10:25,压力测试工具jmeter,实现并发线程的模拟。P69-18:00,演示@SentinelResource注解的使用。 - 作用:sentinel用来替换之前的Hystrix组件保护微服务系统,主要用来解决服务雪崩的问题,有服务熔断(服务降级,服务流控)的机制。
Sentinel-DashBoard的使用
- 直接启动springboot应用jar包(默认端口是8080,指定端口启动):
java -jar -Dserver.port=9191 sentinel-dashboard-1.7.2.jar使用sentinel之前必须安装jdk,并配置环境变量。 - 访问dashboard管理界面(启动之前要关闭防火墙):
http://192.168.200.130:9191,默认用户名和密码:sentinel
[root@rabbitmq ~]# cd sentinel
[root@rabbitmq sentinel]# ls
sentinel-dashboard-1.7.2.jar
[root@rabbitmq sentinel]# java -jar -Dserver.port=9191 sentinel-dashboard-1.7.2.jar
sentinel入门练习
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos-client-->
<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-sentinel</artifactId>
</dependency>
</dependencies>
application.properties
server.port=8998
spring.application.name=SENTINEL
# nacos server
spring.cloud.nacos.server-addr=192.168.200.130:8848
# 开启sentinel保护(默认开启)
spring.cloud.sentinel.enabled=true
# 指定sentinel-dashboard的web地址
spring.cloud.sentinel.transport.dashboard=192.168.200.130:9191
# 指定sentinel组件与sentinel-dashboard组件的通信地址,默认8719(P66-16:00)
spring.cloud.sentinel.transport.port=8719
# 完成sentinel 与 dashboard立即通信
spring.cloud.sentinel.eager=true
DemoController.java
@SpringBootApplication
@EnableDiscoveryClient
public class SentinelApplication {}
//com.jun.controller.DemoController.java
@RestController
public class DemoController {
private static final Logger log = LoggerFactory.getLogger(DemoController.class);
@GetMapping("/demo")
//blockHandler:使用sentinel进行不同规则控制时的默认处理方案。
//fallback:自定义业务出错时默认处理方案。defaultFallback指定一个业务错误时默认方案。
@SentinelResource(value = "aaaa",blockHandler = "blockHandler",
fallback = "fall",defaultFallback = "defaultFall") //代表这是一个sentinel资源
public String demo(Integer id) {
log.info("demo ok ....");
if (id < 0) throw new RuntimeException("id无效");
return "demo ok !!!";
}
//
public String blockHandler(Integer id, BlockException e){
if(e instanceof FlowException){
return "当前请求过于火爆,您已被流控!!!";
}
if(e instanceof DegradeException){
return "当前请求过于火爆,您已被降级!!!";
}
if(e instanceof ParamFlowException){
return "当前请求过于火爆,您已被热点参数限流!!!";
}
return "服务器快爆了,请稍后再试!!!";
}
public String fall(Integer id){
return "自定义服务器出错啦!!!";
}
public String defaultFall(){
return "默认服务器出错啦!!!";
}
@GetMapping("/test")
public String test(){
log.info("test ok ....");
return "test ok ";
}
}
3.整合各个组件练习
构建全局父项目
<groupId>com.jun</groupId>
<artifactId>05springcloud_alibaba_parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>sc01_alibaba_commons</module>
<module>sc02_alibaba_users</module>
<module>sc03_alibaba_products</module>
<module>sc04_alibaba_gateway</module>
</modules>
<!--parent-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<properties>
<spring.cloud.version>Hoxton.SR6</spring.cloud.version>
<spring.cloud.alibaba.version>2.2.1.RELEASE</spring.cloud.alibaba.version>
</properties>
<!--维护springcloud & alibaba-->
<dependencyManagement>
<dependencies>
<!--springcloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--alibaba-->
<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>
</dependencies>
</dependencyManagement>
sc01_alibaba_commons
- 只用来维护公共的实体类、工具类。
sc02_alibaba_users
- 以module为例实现配置的统一管理
pom.xml
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos服务注册中心-->
<!--这个依赖里面已经集成了Ribbon-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--openfeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--nacos-config-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
application.properties
server.port=8888
spring.application.name=USERS
# nacos
spring.cloud.nacos.server-addr=192.168.200.130:8848
# 与sentinel-dashboard建立通信
spring.cloud.sentinel.enabled=true
# 立即初始化,将eager改为true
spring.cloud.sentinel.eager=true
spring.cloud.sentinel.transport.port=8719
spring.cloud.sentinel.transport.dashboard=192.168.200.130:9191
bootstrap.properties
- P70-39:00,将application.properties放到nacos上统一管理,在nacos上新建一个命名空间,如:final。在配置管理处的final空间新建一个配置,Data ID:users-prod.properties ; Group:USERS ; 配置类容为application.properties(去掉中文注释,空格,换行)
#指定远端配置中心
spring.cloud.nacos.server-addr=192.168.200.130:8848
#指定使用nacos中的哪个namespace
spring.cloud.nacos.config.namespace=9fe02401-650a-49a9-b06b-1a60ba5bbf00
#指定使用nacos中的哪个组Group
spring.cloud.nacos.config.group=USERS
#指定使用nacos中的哪个dataId(两种方式):1.name+文件后缀;2.文件名+env+后缀
spring.cloud.nacos.config.name=users-prod
spring.cloud.nacos.config.file-extension=properties
UsersApplication.java
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients //开启openfeign调用
public class UsersApplication {}
com.jun.config
@Configuration
public class BeansConfig {
@Bean
@LoadBalanced //使其具有负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
com.jun.controller
@RestController
public class UserController {
private static final Logger log = LoggerFactory.getLogger(UserController.class);
@Autowired //实现负载均衡,注入restTemplate(P70-25:00)
private RestTemplate restTemplate;
@Autowired
private ProductClient productClient;
@GetMapping("/invoke")
public String invokeProduct(){
log.info("user invoke ok...");
//String result = restTemplate.getForObject("http://PRODUCTS/product", String.class);
//上述这种实现负载均衡的通信方式并不好,存在路径写死的问题。所以
//考虑用OpenFeign的方式。
String result = productClient.product();
log.info("result:{}",result);
return result;
}
}
com.jun.feignclients
@FeignClient("PRODUCTS")
public interface ProductClient {
@GetMapping("/product")
String product();
}
sc03_alibaba_products
pom.xml
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
application.properties
server.port=9999
spring.application.name=PRODUCTS
# nacos
spring.cloud.nacos.server-addr=192.168.200.130:8848
ProductsApplication.java
@SpringBootApplication
@EnableDiscoveryClient //可以省略
public class ProductsApplication {}
com.jun.controller
@RestController
public class ProductController {
private static final Logger log = LoggerFactory.getLogger(ProductController.class);
@Value("${server.port}")
private int port;
@GetMapping("/product")
public String product(){
log.info("product ok....");
return "product ok,当前服务端口号为: "+port;
}
}
sc04_alibaba_gateway
pom.xml
<!--gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--gateway也需要注册到nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--将配置文件放到远端,需要nacos-config-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
application.yml
server:
port: 8990
spring:
application:
name: GATEWAY
cloud:
nacos:
server-addr: 192.168.200.130:8848
gateway: # 指定网关的路由规则
routes:
- id: users_route
# uri: http://localhost:8888 # 这样写没有负载均衡的效果
uri: lb://USERS
predicates:
- Path=/invoke
- id: product_route
# uri: http://localhost:9999
uri: lb://PRODUCTS
predicates:
- Path=/product
bootstrap.properties
- P70-45:00,将网关的yml配置文件放到远端,在final命名空间里新建配置:Data ID:gateway-prod.yml;Group:Gateway;将application.yml中的类容放到配置类容。
#指定远端配置中心是谁
spring.cloud.nacos.server-addr=192.168.200.130:8848
#指定使用nacos中的哪个namespace
spring.cloud.nacos.config.namespace=9fe02401-650a-49a9-b06b-1a60ba5bbf00
#指定使用nacos中的哪个组
spring.cloud.nacos.config.group=GATEWAY
#指定使用nacos中的哪个dataId(两种方式):1.name+文件后缀;2.文件名+env+后缀
spring.cloud.nacos.config.name=gateway-prod
spring.cloud.nacos.config.file-extension=yml
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {}