SpringCloud 笔记(下)

82 阅读8分钟

SpringCloud Alibaba 入门简介

诞生: 2018.10.31,Spring Cloud Alibaba 正式入驻了 Spring Cloud 官方孵化器,并在 Maven 中央库发布了第一个版本。

能干嘛?

服务限流降级:默认支持 Servlet、Feign、RestTemplate、Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。 服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。 消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。 分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。

SpringCloud Alibaba Nacos服务注册和配置中心

nacos的简介:

image.png

各注册中心比较:

image.png

Nacos作为服务注册中心演示

基于Nacos的服务提供者

  • 导入依赖

  • yml

server:
  port: 9001

spring:
  application:
    name: nacos-payment-provider
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8001 #配置Nacos地址

management:
  endpoints:
    web:
      exposure:
        include: '*'
  • controller
@RestController
public class PaymentController
{
    @Value("${server.port}")
    private String serverPort;

    @GetMapping(value = "/payment/nacos/{id}")
    public String getPayment(@PathVariable("id") Integer id)
    {
        return "nacos registry, serverPort: "+ serverPort+"\t id"+id;
    }
}
  • 测试

image.png

服务nacos-payment-provider 注册到了nacos image.png

基于Nacos的服务消费者 调用提供者9001和9002,实现负载均衡

  • 导入依赖

  • yml

server:
  port: 83


spring:
  application:
    name: nacos-order-consumer
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8001


#消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
  nacos-user-service: http://nacos-payment-provider
  • nacos中集成了ribon,编写ApplicationContextConfig类,引入RestTemplate
@Configuration
public class ApplicationContextConfig
{
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate()
    {
        return new RestTemplate();
    }
}
  • controller
@RestController
@Slf4j
public class OrderNacosController
{
    @Resource
    private RestTemplate restTemplate;

    @Value("${service-url.nacos-user-service}")
    private String serverURL;

    @GetMapping(value = "/consumer/payment/nacos/{id}")
    public String paymentInfo(@PathVariable("id") Long id)
    {
        return restTemplate.getForObject(serverURL+"/payment/nacos/"+id,String.class);
    }

}

image.png

image.png

image.png

服务注册中心对比

image.png

image.png

 

  • C是所有节点在同一时间看到的数据是一致的;而A的定义是所有的请求都会收到响应。
  • 何时选择使用何种模式?
  • 一般来说,如果不需要存储服务级别的信息且服务实例是通过nacos-client注册,并能够保持心跳上报,那么就可以选择AP模式。当前主流的服务如 Spring cloud 和 Dubbo 服务,都适用于AP模式,AP模式为了服务的可能性而减弱了一致性,因此AP模式下只支持注册临时实例。 
  • 如果需要在服务级别编辑或者存储配置信息,那么 CP 是必须,K8S服务和DNS服务则适用于CP模式。CP模式下则支持注册持久化实例,此时则是以 Raft 协议为集群运行模式,该模式下注册实例之前必须先注册服务,如果服务不存在,则会返回错误。

curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'

Nacos作为服务配置中心演示

image.png  

  • yml
# nacos配置
server:
  port: 3377

spring:
  application:
    name: nacos-config-client
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8001 #Nacos服务注册中心地址
      config:
        server-addr: localhost:8001 #Nacos作为配置中心地址
        file-extension: yaml #指定yaml格式的配置
#        group: DEV_GROUP
#        namespace: 7d8f0f5a-6a53-4785-9686-dd460158e5d4


# ${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
# nacos-config-client-dev.yaml

# nacos-config-client-test.yaml   ----> config.info
spring:
  profiles:
    active: dev # 表示开发环境
    #active: test # 表示测试环境
    #active: info

注意nacos上配置中心文件的名字

  • controller,注解@RefreshScope支持动态刷新
@RestController
@RefreshScope //支持Nacos的动态刷新功能。
public class ConfigClientController
{
    @Value("${config.info}")
    private String configInfo;

    @GetMapping("/config/info")
    public String getConfigInfo() {
        return configInfo;
    }
}
  • 测试

image.png

image.png

Nacos作为配置中心-分类配置

image.png  

1 是什么

   类似Java里面的package名和类名    最外层的namespace是可以用于区分部署环境的,Group和DataID逻辑上区分两个目标对象。

2 三者情况    

默认情况:

  • Namespace=public,Group=DEFAULT_GROUP, 默认Cluster是DEFAULT
  • Nacos默认的命名空间是public,Namespace主要用来实现隔离。比方说我们现在有三个环境:开发、测试、生产环境,我们就可以创建三个Namespace,不同的Namespace之间是隔离的。
  • Group默认是DEFAULT_GROUP,Group可以把不同的微服务划分到同一个分组里面去
  • Service就是微服务;一个Service可以包含多个Cluster(集群),Nacos默认Cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。比方说为了容灾,将Service微服务分别部署在了杭州机房和广州机房,这时就可以给杭州机房的Service微服务起一个集群名称(HZ),给广州机房的Service微服务起一个集群名称(GZ),还可以尽量让同一个机房的微服务互相调用,以提升性能。 
  • 最后是Instance,就是微服务的实例。         image.png        

Nacos集群和持久化配置(重要)

  image.png   image.png     image.png  

  • application.properties
spring.datasource.platform=mysql
db.num=1
db.url=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=123

 

Linux版Nacos+MySQL生产环境配置

image.png  

  •  Linux服务器上nacos的集群配置cluster.conf hostname -i

192.168.152.130

image.png  

image.png

image.png

  • Nginx的配置,由它作为负载均衡器

image.png

 upstream cluster{        
 server 127.0.0.1:3333;        
 server 127.0.0.1:4444;        
 server 127.0.0.1:5555;    
 }
 server {        
     listen       1111;        
     server_name  localhost;        
     #charset koi8-r;        
     #access_log  logs/host.access.log  main;        
     location / {            
          #root   html;            
          #index  index.html index.htm;            
          proxy_pass http://cluster;        
     }.......省略
 

upstream是nginx的负载均衡ip映射配置

  • 启动linux中3台nacos 进去bin目录

cd /mynacos/bin

./startup.sh -p 3333
./startup.sh -p 4444
./startup.sh -p 5555

image.png

  • 查看nacos启动端口 ps -ef |grep nacos|grep -v grep |wc -l

image.png

出现的问题: 1.不成功的有失败信息。因为nacos运行需要的内存不小,一般可能是因为内存不足,内存不足信息:

image.png

修改内存大小

image.png

修改后

image.png

内存给的太小会打不开nacos

2.nginx: [emerg] unknown directive "     " in /usr/local/nginx/conf/nginx.conf:39

手敲配置文件,因为格式会有问题

  • 启动nginx 1.进入nginx的sbin目录
cd /usr/local/nginx/sbin

2.输入nginx启动命令

./nginx -c /usr/local/nginx/conf/nginx.conf

3.查看是否启动nginx

ps -ef |grep nginx

image.png

http://192.168.152.130:1111/nacos/#/login

nacos集群启动问题:

  • 1.启动模式由单机改为集群
  • 2.JVM分配内存改动以下,不能改太小
  • 3.复制3个nacos,改动端口分别启动
  • 4.改变配置文件
  • 5.启动脚本
 cd /mynacos/bin
 ./startup.sh
 
 /mynacos3999/bin
  ./startup.sh
  • 测试 访问linux中nacos端口 image.png

通过nginx端口1111成功访问到集群nacos端口 image.png

  • 在配置中心新增一条配置

image.png

  • 在linux中查询mysql数据库,可以查到此数据

image.png

  • 把9002nacos-payment-provider注册进去linux的nacos中 yml
server:
  port: 9002

spring:
  application:
    name: nacos-payment-provider
  cloud:
    nacos:
      discovery:
#        server-addr: localhost:8001 #配置Nacos地址
        # 换成nginx的1111端口,做集群
        server-addr: 192.168.152.130:1111

management:
  endpoints:
    web:
      exposure:
        include: '*'

image.png

总结:

image.png

SpringCloud Sleuth 分布式请求链路跟踪

Sleuth启动

java -jar -文件名

- cloudalibaba-sentinel-service8401实例

yml

server:
  port: 8401

spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8001 #Nacos服务注册中心地址
    sentinel:
      transport:
        dashboard: localhost:8080 #配置Sentinel dashboard地址
        port: 8719
#      datasource:
#        ds1:
#          nacos:
#            server-addr: localhost:8848
#            dataId: cloudalibaba-sentinel-service
#            groupId: DEFAULT_GROUP
#            data-type: json
#            rule-type: flow

#management:
#  endpoints:
#    web:
#      exposure:
#        include: '*'
#
#feign:
#  sentinel:
#    enabled: true # 激活Sentinel对Feign的支持

image.png image.png

流控规则

基本介绍:

image.png

进一步说明:

image.png

image.png

QPS和线程数的区别:

QPS是某一秒最大访问量 线程数是要等某个线程执行完后其他线程才能执行 image.png

关联:

image.png

使用postman并发访问testB:

image.png

降级规则

基本介绍:

image.png

image.png

例子:

image.png

image.png

image.png 例子:

image.png image.png image.png 例子:

image.png

热点key限流

controller层:blockHandler是兜底方法,SentinelResource注解中的value是资源名,方便找到热点参数。

@GetMapping("/testHotKey")
@SentinelResource(value = "testHotKey",blockHandler = "deal_testHotKey")
public String testHotKey(@RequestParam(value = "p1",required = false) String p1,
                         @RequestParam(value = "p2",required = false) String p2)
{
    //int age = 10/0;
    return "------testHotKey";
}
public String deal_testHotKey (String p1, String p2, BlockException exception)
{
    return "------deal_testHotKey,o(╥﹏╥)o";  //sentinel系统默认的提示:Blocked by Sentinel (flow limiting)
}

image.png

image.png

image.png

参数例外项:

相当于如果用户是VIP则不限制 image.png

@SentinelResource 注解

image.png 用户自定义限流处理逻辑:

image.png

image.png

84调用9003和9004,Sentinel的使用

为什么不用全局异常处理,用fallback,因为服务之间的调用。 用fallback表示程序发生异常的兜底处理。 blockHandler 是sentinel控制台配置违规,比如设定了降级规则,违反了就触发。

@RequestMapping("/consumer/fallback/{id}")
//@SentinelResource(value = "fallback") //没有配置
//@SentinelResource(value = "fallback",fallback = "handlerFallback") //fallback只负责业务异常
//@SentinelResource(value = "fallback",blockHandler = "blockHandler") //blockHandler只负责sentinel控制台配置违规
@SentinelResource(value = "fallback",fallback = "handlerFallback",blockHandler = "blockHandler",
        exceptionsToIgnore = {IllegalArgumentException.class})
public CommonResult<Payment> fallback(@PathVariable Long id)
{
    CommonResult<Payment> result = restTemplate.getForObject(SERVICE_URL + "/paymentSQL/"+id,CommonResult.class,id);

    if (id == 4) {
        throw new IllegalArgumentException ("IllegalArgumentException,非法参数异常....");
    }else if (result.getData() == null) {
        throw new NullPointerException ("NullPointerException,该ID没有对应记录,空指针异常");
    }

    return result;
}

image.png

sentinel服务熔断Feign

  • yml
# 激活Sentinel对Feign的支持
feign:
  sentinel:
    enabled: true
  • 主启动类
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class OrderNacosMain84
{
    public static void main(String[] args) {
        SpringApplication.run(OrderNacosMain84.class, args);
    }
}
  • service层
@FeignClient(value = "nacos-payment-provider",fallback = PaymentFallbackService.class)
public interface PaymentService
{
    @GetMapping(value = "/paymentSQL/{id}")
    public CommonResult<Payment> paymentSQL(@PathVariable("id") Long id);
}
  • 兜底类
@Component
public class PaymentFallbackService implements PaymentService
{
    @Override
    public CommonResult<Payment> paymentSQL(Long id)
    {
        return new CommonResult<>(44444,"服务降级返回,---PaymentFallbackService",new Payment(id,"errorSerial"));
    }
}

测试84调用9003,此时故意关闭9003微服务提供者,看84消费侧自动降级,不会被耗死

规则持久化

  • 一旦我们重启应用,sentinel规则将消失,生产环境需要将配置规则进行持久化
  • 将限流配置规则持久化进Nacos保存,只要刷新8401某个rest地址,sentinel控制台的流控规则就能看到,只要Nacos里面的配置不删除,针对8401上sentinel上的流控规则持续有效

image.png

nacos配置:

 
[
    {
        "resource": "/rateLimit/byUrl",
        "limitApp": "default",
        "grade": 1,
        "count": 1,
        "strategy": 0,
        "controlBehavior": 0,
        "clusterMode": false
    }
]

 resource:资源名称;
 limitApp:来源应用;
 grade:阈值类型,0表示线程数,1表示QPS;
 count:单机阈值;
 strategy:流控模式,0表示直接,1表示关联,2表示链路;
 controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;clusterMode:是否集群。

SpringCloud Alibaba Seata处理分布式事务