SpringCloudAlibaba

183 阅读2分钟

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 组件

  1. 服务注册与发现组件:eureka、consul =》 nacos
  2. 服务间通信组件:RestTemplate+ribbon,Openfeign =》restTemplate+ribbon,Openfeign

服务间的通信有两种方式:1.Http Rest(推荐) 2.RPC。使用Rest方式实现服务间通信:①使用spring框架为我们提供的RestTemplate,但没法实现负载均衡。②RestTemplate+Ribbon,可以实现负载均衡,但地址耦合严重。所以更推荐使用 ③OpenFeign方式调用。

  1. 服务降级和熔断:hystrix、hystrix dashboard =》sentinel
  2. 服务网关组件:zuul1.x/zuul2.x、gateway =》gateway
  3. 统一配置中心组件,消息总线组件: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 截图_20213516013511.png

父项目中依赖维护

<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

Nacos_20213916053913.png image.png

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 {}