SpringCloud Alibaba 学习

news2024/10/7 16:23:29

一:SpringCloud Alibaba介绍

Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服
务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。
依托 Spring Cloud Alibaba,您只需要添加一些注解和少量配置,就可以将 Spring Cloud 应用接
入阿里微服务解决方案,通过阿里中间件来迅速搭建分布式应用系统。

主要功能

服务限流降级:默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud
Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修
改限流降级规则,还支持查看限流降级 Metrics 监控。
服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。
分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。
阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任
何时间、任何地点存储和访问任意类型的数据。
分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有
Worker(schedulerx-client)上执行。
阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建
客户触达通道

二:微服务环境搭建

备注:将搭建好的环境进行备份,以便练习

2.1 数据库准备

创建数据库
在这里插入图片描述

2.3 创建工程

结构图
在这里插入图片描述
pom

<?xml version="1.0" encoding="UTF-8"?>
<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>com.yc</groupId>
    <artifactId>springcloud-alibaba-02</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>shop-common</module>
        <module>shop-user</module>
        <module>shop-product</module>
        <module>shop-order</module>
    </modules>

    <!--  父工程   -->
    <parent>
        <artifactId>spring-boot-starter-parent</artifactId>
        <groupId>org.springframework.boot</groupId>
        <version>2.1.3.RELEASE</version>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <!--        <spring-cloud.version>Greenwich.RELEA</spring-cloud.version>-->
        <!--        <spring-cloud-alibaba.version>2.1.1.RELEASE</spring-cloud-alibaba.version>-->
        <spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version>
    </properties>


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

2.4 shop-common 模块

1.pom依赖

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <parent>
        <artifactId>springcloud-alibaba-02</artifactId>
        <groupId>com.yc</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>shop-common</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.56</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
    </dependencies>

</project>

2.结构
在这里插入图片描述
3.实体类
Order

package com.yc.domain;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.domain
 * @Date 2024/3/4 18:17
 */
@Entity(name = "shop_order")
@Data
public class Order {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long oid;//订单id
    private Integer uid;//用户id
    private String username;//用户名

    private Integer pid;//商品id
    private String pname;//商品名称
    private Double pprice;//商品单价
    private Integer number;//购买数量
}

Product

package com.yc.domain;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.domain
 * @Date 2024/3/4 18:18
 */
@Entity(name = "shop_product")
@Data
public class Product {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer pid;//主键
    private String pname;//商品名称
    private Double pprice;//商品价格
    private Integer stock;//库存
}

** User**

package com.yc.domain;

import lombok.Data;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.domain
 * @Date 2024/3/4 18:17
 */
@Entity(name = "shop_user")
@Data
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer uid;//主键
    private String username;//用户名
    private String password;//密码
    private String telephone;//手机号
}

2.5 shop-user 模块

1.pom

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <parent>
        <artifactId>springcloud-alibaba-02</artifactId>
        <groupId>com.yc</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>shop-user</artifactId>


    <dependencies>
        <dependency>
            <groupId>com.yc</groupId>
            <artifactId>shop-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

2.结构
在这里插入图片描述
3.启动类

package com.yc;

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


/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc
 * @Date 2024/3/4 18:22
 */
@SpringBootApplication
public class UserApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class,args);
    }
}

4.配置文件 application.yml

server:
  port: 8071
spring:
  application:
    name: service-product
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///hmshop02?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    username: ****
    password: ****
  jpa:## 自动生成数据库表配置
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        dialect: org.hibernate.dialect.MySQL5InnoDBDialect

2.6 shop_product 模块

1.pom

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <parent>
        <artifactId>springcloud-alibaba-02</artifactId>
        <groupId>com.yc</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>shop-product</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yc</groupId>
            <artifactId>shop-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

2.结构
在这里插入图片描述
3.启动类

package com.yc;

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

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc
 * @Date 2024/3/4 18:29
 */
@SpringBootApplication
public class ProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProductApplication.class,args);
    }
}

4.配置文件 application.yml

server:
  port: 18082
spring:
  application:
    name: service-product
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///hmshop02?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    username: root
    password: 123456
  jpa:
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        dialect: org.hibernate.dialect.MySQL5InnoDBDialect

5.ProductController

package com.yc.controller;

import com.alibaba.fastjson.JSON;
import com.yc.domain.Product;
import com.yc.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.controller
 * @Date 2024/3/4 18:33
 */
@RestController
@Slf4j
public class ProductController {

    @Autowired
    private ProductService productService;

    @GetMapping("/product/{pid}")
    public Product product(@PathVariable("pid") Integer pid) {
        Product product = productService.findByPid(pid);
        log.info("查询到商品:" + JSON.toJSONString(product));
        return product;
    }

}

6.ProductDao

package com.yc.dao;

import com.yc.domain.Product;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.dao
 * @Date 2024/3/4 18:31
 */
public interface ProductDao extends JpaRepository<Product,Integer> {
}

7.ProductService

package com.yc.service;

import com.yc.domain.Product;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.service
 * @Date 2024/3/4 18:31
 */
public interface ProductService {
    Product findByPid(Integer pid);
}

8.ProductServiceImpl

package com.yc.service.impl;

import com.yc.dao.ProductDao;
import com.yc.domain.Product;
import com.yc.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.service.impl
 * @Date 2024/3/4 18:32
 */
@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductDao productDao;

    @Override
    public Product findByPid(Integer pid) {
        return productDao.findById(pid).get();
    }
}

9.启动后查看数据库
在这里插入图片描述
10.写入测试数据

INSERT INTO shop_product VALUE(NULL,'小米','1000','5000');
INSERT INTO shop_product VALUE(NULL,'华为','2000','5000');
INSERT INTO shop_product VALUE(NULL,'苹果','3000','5000');
INSERT INTO shop_product VALUE(NULL,'OPPO','4000','5000');

11.通过浏览器访问服务
http://localhost:18082/product/1
在这里插入图片描述

2.7 shop-order 模块

1.pom

<?xml version="1.0" encoding="UTF-8"?>
<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">
    <parent>
        <artifactId>springcloud-alibaba-02</artifactId>
        <groupId>com.yc</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>shop-order</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.yc</groupId>
            <artifactId>shop-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project>

2.结构
在这里插入图片描述
3.启动类

package com.yc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc
 * @Date 2024/3/4 18:39
 */
@SpringBootApplication
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

4.application.yml

server:
  port: 8091
spring:
  application:
    name: service-product
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///hmshop02?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    username: root
    password: 123456
  jpa:
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        dialect: org.hibernate.dialect.MySQL5InnoDBDialect

5.OrderController

package com.yc.controller;

import com.alibaba.fastjson.JSON;
import com.yc.domain.Order;
import com.yc.domain.Product;
import com.yc.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.controller
 * @Date 2024/3/4 18:45
 */
@RestController
@Slf4j
public class OrderController {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private OrderService orderService;
    //准备买1件商品
    @GetMapping("/order/prod/{pid}")
    public Order order(@PathVariable("pid") Integer pid) {
        log.info(">>客户下单,这时候要调用商品微服务查询商品信息");
        //通过restTemplate调用商品微服务
        Product product = restTemplate.getForObject("http://localhost:18082/product/" + pid, Product.class);
        log.info(">>商品信息,查询结果:" + JSON.toJSONString(product));
        Order order = new Order();
        order.setUid(1);
        order.setUsername("测试用户");
        order.setPid(product.getPid());
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);
        orderService.save(order);
        return order;
    }
}

6.OrderDao

package com.yc.dao;

import com.yc.domain.Order;
import org.springframework.data.jpa.repository.JpaRepository;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.dao
 * @Date 2024/3/4 18:42
 */
public interface OrderDao extends JpaRepository<Order,Long> {
}

7.OrderService

package com.yc.service;

import com.yc.domain.Order;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.service
 * @Date 2024/3/4 18:42
 */
public interface OrderService {
    void save(Order order);
}

8.OrderServiceImpl

package com.yc.service.impl;

import com.yc.dao.OrderDao;
import com.yc.domain.Order;
import com.yc.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.service.impl
 * @Date 2024/3/4 18:43
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;

    @Override
    public void save(Order order) {
        orderDao.save(order);
    }

}

9启动后浏览器访问
http://localhost:8091/order/prod/1
在这里插入图片描述

三 Nacos Discovery–服务治理

什么是服务治理

服务治理是微服务架构中最核心最基本的模块。用于实现各个微服务的自动化注册与发现。

  • 服务注册:在服务治理框架中,都会构建一个注册中心,每个服务单元向注册中心登记自己提供服
    务的详细信息。并在注册中心形成一张服务的清单,服务注册中心需要以心跳的方式去监测清单中
    的服务是否可用,如果不可用,需要在服务清单中剔除不可用的服务。
  • 服务发现:服务调用方向服务注册中心咨询服务,并获取所有服务的实例清单,实现对具体服务实
    例的访问。
    在这里插入图片描述
    通过上面的调用图会发现,除了微服务,还有一个组件是服务注册中心,它是微服务架构非常重要
    的一个组件,在微服务架构里主要起到了协调者的一个作用。注册中心一般包含如下几个功能:
  1. 服务发现:
    服务注册:保存服务提供者和服务调用者的信息
    服务订阅:服务调用者订阅服务提供者的信息,注册中心向订阅者推送提供者的信息
  2. 服务配置:
    配置订阅:服务提供者和服务调用者订阅微服务相关的配置
    配置下发:主动将配置推送给服务提供者和服务调用者
  3. 服务健康检测
    检测服务提供者的健康情况,如果发现异常,执行服务剔除

3.1 nacos简介

Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速
实现动态服务发现、服务配置、服务元数据及流量管理。
从上面的介绍就可以看出,nacos的作用就是一个注册中心,用来管理注册上来的各个微服务。

3.2 ncaos实战入门

1.搭建nacos环境

第1步: 安装nacos
备注 :以windos系统为例子

下载地址: https://github.com/alibaba/nacos/releases
下载zip格式的安装包,然后进行解压缩操作
官方文档:https://nacos.io/zh-cn/docs/quick-start.html
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第2步:修改配置

在这里插入图片描述
在这里插入图片描述

第3步: 启动nacos
在这里插入图片描述
在这里插入图片描述

第4步: 访问nacos

打开浏览器输入http://localhost:8848/nacos,即可访问服务, 默认密码是nacos/nacos
在这里插入图片描述

2.将所有模块注册到nacos

shop-order 模块 shop-product 模块 shop-user模块

1 在pom.xml中添加nacos的依赖

<!--nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2 在主类上添加@EnableDiscoveryClient注解
在这里插入图片描述
3 在application.yml中添加nacos服务的地址

spring:
	cloud:
		nacos:
			discovery:
				server-addr: 127.0.0.1:8848

在这里插入图片描述
4 启动服务, 观察nacos的控制面板中是否有注册上来的微服务
在这里插入图片描述

3.修改OrderController, 实现微服务调用

修改OrderController, 实现微服务调用
DiscoveryClient是专门负责服务注册和发现的,我们可以通过它获取到注册到注册中心的所有服

OrderController中注入依赖

@Autowired
    private DiscoveryClient discoveryClient;

将通过restTemplate直接调用商品微服务 ,改为通过 nacos中获取服务地址

//从nacos中获取服务地址
        ServiceInstance serviceInstance =
                discoveryClient.getInstances("service-product").get(0);
        String url = serviceInstance.getHost() + ":" +
                serviceInstance.getPort();
        log.info(">>从nacos中获取到的微服务地址为:" + url);
//通过restTemplate调用商品微服务
        Product product = restTemplate.getForObject(
                "http://" + url + "/product/" + pid, Product.class);

        /*
        //通过restTemplate直接调用商品微服务
        Product product = restTemplate.getForObject("http://localhost:18082/product/" + pid, Product.class);
        */

重新启动订单服务,
重启后 访问浏览器 : http://localhost:8091/order/prod/1

在这里插入图片描述

四:Ribbon实现负载均衡

Ribbon是Spring Cloud的一个组件, 它可以让我们使用一个注解就能轻松的搞定负载均衡
链接: Ribbon负载均衡
1.启动两个shop-product 微服务
在这里插入图片描述
-Dserver.port=18084
在这里插入图片描述
在这里插入图片描述
2:在RestTemplate 的生成方法上添加@LoadBalanced注解

package com.yc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc
 * @Date 2024/3/4 18:39
 */
@SpringBootApplication
@EnableDiscoveryClient
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

3:修改服务调用的方法

package com.yc.controller;

import com.alibaba.fastjson.JSON;
import com.yc.domain.Order;
import com.yc.domain.Product;
import com.yc.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.controller
 * @Date 2024/3/4 18:45
 */
@RestController
@Slf4j
public class OrderController {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private OrderService orderService;

    @Autowired
    private DiscoveryClient discoveryClient;

    //准备买1件商品
    @GetMapping("/order/prod/{pid}")
    public Order order(@PathVariable("pid") Integer pid) {
        log.info(">>客户下单,这时候要调用商品微服务查询商品信息");

        //直接使用微服务名字, 从nacos中获取服务地址
        String url = "service-product01";
        //通过restTemplate调用商品微服务
        Product product = restTemplate.getForObject("http://" + url + "/product/" + pid, Product.class);
        
        /*
        //从nacos中获取服务地址
        ServiceInstance serviceInstance = discoveryClient.getInstances("service-product01").get(0);
        String url = serviceInstance.getHost() + ":" + serviceInstance.getPort();
        log.info(">>从nacos中获取到的微服务地址为:" + url);
        //通过restTemplate调用商品微服务
        Product product = restTemplate.getForObject("http://" + url + "/product/" + pid, Product.class);
        */
        /*
        //通过restTemplate调用商品微服务
        Product product = restTemplate.getForObject("http://localhost:18082/product/" + pid, Product.class);
        */
        log.info(">>商品信息,查询结果:" + JSON.toJSONString(product));
        Order order = new Order();
        order.setUid(1);
        order.setUsername("测试用户");
        order.setPid(product.getPid());
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);
        orderService.save(order);
        return order;
    }
}

4.通过修改配置来调整Ribbon的负载均衡策略

# ribbon 实现负载均衡
service-product: # 调用的提供者的名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #随机进行负载

5.重启后 访问浏览器
多次范围跟: http://localhost:8091/order/prod/1
shop-order服务日志
在这里插入图片描述
shop-product01服务日志
在这里插入图片描述

shop-product02服务日志
在这里插入图片描述

五:Feign实现服务调用

Feign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地服务
一样简单, 只需要创建一个接口并添加一个注解即可。
Nacos很好的兼容了Feign, Feign默认集成了 Ribbon, 所以在Nacos下使用Fegin默认就实现了负
载均衡的效果。
链接: Feign服务调用

1 加入Fegin的依赖

<!--fegin组件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2 在主类上添加Fegin的注解

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients //开启fegin
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

3 创建一个service, 并使用Fegin实现微服务调用
在这里插入图片描述

package com.yc.service;

import com.yc.domain.Product;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.service
 * @Date 2024/3/5 17:54
 */
@FeignClient("service-product01")//声明调用的提供者的name
public interface ProudService {

    //指定调用提供者的哪个方法
    //@FeignClient+@GetMapping 就是一个完整的请求路径 http://serviceproduct/product/{pid}
    @GetMapping(value = "/product/{pid}")
    Product findByPid(@PathVariable("pid") Integer pid);
    
    
}

4 修改controller代码,并启动验证

package com.yc.controller;

import com.alibaba.fastjson.JSON;
import com.yc.domain.Order;
import com.yc.domain.Product;
import com.yc.service.OrderService;
import com.yc.service.ProudService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.controller
 * @Date 2024/3/4 18:45
 */
@RestController
@Slf4j
public class OrderController {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private OrderService orderService;

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private ProudService productService;

    //准备买1件商品
    @GetMapping("/order/prod/{pid}")
    public Order order(@PathVariable("pid") Integer pid) {
        log.info(">>客户下单,这时候要调用商品微服务查询商品信息");

//通过fegin调用商品微服务
        Product product = productService.findByPid(pid);

        /*
        //直接使用微服务名字, 从nacos中获取服务地址
        String url = "service-product01";
        //通过restTemplate调用商品微服务
        Product product = restTemplate.getForObject("http://" + url + "/product/" + pid, Product.class);
        */

        /*
        //从nacos中获取服务地址
        ServiceInstance serviceInstance = discoveryClient.getInstances("service-product01").get(0);
        String url = serviceInstance.getHost() + ":" + serviceInstance.getPort();
        log.info(">>从nacos中获取到的微服务地址为:" + url);
        //通过restTemplate调用商品微服务
        Product product = restTemplate.getForObject("http://" + url + "/product/" + pid, Product.class);
        */
        /*
        //通过restTemplate调用商品微服务
        Product product = restTemplate.getForObject("http://localhost:18082/product/" + pid, Product.class);
        */
        log.info(">>商品信息,查询结果:" + JSON.toJSONString(product));
        Order order = new Order();
        order.setUid(1);
        order.setUsername("测试用户");
        order.setPid(product.getPid());
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());
        order.setNumber(1);
        orderService.save(order);
        return order;
    }
}

5 重启order微服务, 浏览器访问查看效果
http://localhost:8091/order/prod/1
在这里插入图片描述

六:Sentinel–服务容错

什么是Sentinel

Sentinel (分布式系统的流量防卫兵) 是阿里开源的一套用于服务容错的综合性解决方案。它以流量
为切入点, 从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。
Sentinel 具有以下特征:
丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景, 例如秒杀(即
突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用
应用等。
完备的实时监控:Sentinel 提供了实时的监控功能。通过控制台可以看到接入应用的单台机器秒
级数据, 甚至 500 台以下规模的集群的汇总运行情况。
广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块, 例如与 Spring
Cloud、Dubbo、gRPC 的整合。只需要引入相应的依赖并进行简单的配置即可快速地接入
Sentinel
完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快
速地定制逻辑。例如定制规则管理、适配动态数据源等

Sentinel 分为两个部分:

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

链接: Sentinel 服务容错

6.1服务雪崩效应

在分布式系统中,由于网络原因或自身的原因,服务一般无法保证 100% 可用。如果一个服务出现了
问题,调用这个服务就会出现线程阻塞的情况,此时若有大量的请求涌入,就会出现多条线程阻塞等
待,进而导致服务瘫痪。
由于服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是
服务故障的 “雪崩效应” 。

在这里插入图片描述

雪崩发生的原因多种多样,有不合理的容量设计,或者是高并发下某一个方法响应变慢,亦或是某
台机器的资源耗尽。我们无法完全杜绝雪崩源头的发生,只有做好足够的容错,保证在一个服务发生问
题,不会影响到其它服务的正常运行。也就是"雪落而不雪崩"。

6.2 常见容错方案

要防止雪崩的扩散,我们就要做好服务的容错,容错说白了就是保护自己不被猪队友拖垮的一些措
施, 下面介绍常见的服务容错思路和组件。

常见的容错思路

常见的容错思路有隔离、超时、限流、熔断、降级这几种,下面分别介绍一下。

隔离
它是指将系统按照一定的原则划分为若干个服务模块,各个模块之间相对独立,无强依赖。当有故
障发生时,能将问题和影响隔离在某个模块内部,而不扩散风险,不波及其它模块,不影响整体的
系统服务。常见的隔离方式有:线程池隔离和信号量隔离.
在这里插入图片描述
超时
在上游服务调用下游服务的时候,设置一个最大响应时间,如果超过这个时间,下游未作出反应,
就断开请求,释放掉线程。
在这里插入图片描述

限流
限流就是限制系统的输入和输出流量已达到保护系统的目的。为了保证系统的稳固运行,一旦达到
的需要限制的阈值,就需要限制流量并采取少量措施以完成限制流量的目的。
在这里插入图片描述

熔断
在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整
体的可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断。
在这里插入图片描述
服务熔断一般有三种状态:

  • 熔断关闭状态(Closed)
    服务没有故障时,熔断器所处的状态,对调用方的调用不做任何限制
  • 熔断开启状态(Open)
    后续对该服务接口的调用不再经过网络,直接执行本地的fallback方法
  • 半熔断状态(Half-Open)
    尝试恢复服务调用,允许有限的流量调用该服务,并监控调用成功率。如果成功率达到预
    期,则说明服务已恢复,进入熔断关闭状态;如果成功率仍旧很低,则重新进入熔断关闭状

    降级
    降级其实就是为服务提供一个托底方案,一旦服务无法正常调用,就使用托底方案。
    在这里插入图片描述

6.3 集成Sentinel

1 在pom.xml中加入下面依赖

<!--Sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

2 编写一个Controller测试使用
在这里插入图片描述

package com.yc.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author yc
 * @PackageName springcloud-alibaba-02
 * @Package com.yc.controller
 * @Date 2024/3/5 18:11
 */
@RestController
@Slf4j
public class OrderControllerTest001 {

    @RequestMapping("/order/message1")
    public String message1() {
        return "message1";
    }

    @RequestMapping("/order/message2")
    public String message2() {
        return "message2";
    }

}

6.4 安装Sentinel控制台

Sentinel 提供一个轻量级的控制台, 它提供机器发现、单机资源实时监控以及规则管理等功能。
1 下载jar包,解压到文件夹
https://github.com/alibaba/Sentinel/releases
在这里插入图片描述
2 启动控制台

监听端口 + sentinel 服务端口地址 + 项目名称 + 运行sentinel的jar包

# 直接使用jar命令启动项目(控制台本身是一个SpringBoot项目)
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -
Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7.0.jar

3 修改 shop-order模块配置类 ,在里面加入有关控制台的配置

server:
  port: 8091
spring:
  application:
    name: service-order02
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.93.1:8848
    sentinel:
      transport:
        port: 18081 #跟控制台交流的端口,随意指定一个未使用的端口即可
        dashboard: localhost:18080 # 指定控制台服务的地址
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql:///hmshop02?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=true
    username: root
    password: 123456
  jpa:
    properties:
      hibernate:
        hbm2ddl:
          auto: update
        dialect: org.hibernate.dialect.MySQL5InnoDBDialect

# ribbon 实现负载均衡
service-product: # 调用的提供者的名称
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #随机进行负载

第4步: 通过浏览器访问 http://localhost:8091/order/message1
在这里插入图片描述

第5步: 通过浏览器访问localhost:18080 进入控制台 ( 默认用户名密码是 sentinel/sentinel )
在这里插入图片描述

补充:了解控制台的使用原理
Sentinel的控制台其实就是一个SpringBoot编写的程序。我们需要将我们的微服务程序注册到控制台上,
即在微服务中指定控制台的地址, 并且还要开启一个跟控制台传递数据的端口, 控制台也可以通过此端口
调用微服务中的监控程序获取微服务的各种信息
在这里插入图片描述

6.5 实现接口限流

1 通过控制台为message1添加一个流控规则
在这里插入图片描述
在这里插入图片描述
2 通过控制台快速频繁访问, 观察效果
在这里插入图片描述

6.6 Sentinel的概念和功能

1.基本概念

资源
资源就是Sentinel要保护的东西
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,可以是一个服务,也可以是
一个方法,甚至可以是一段代码。
我们入门案例中的message1方法就可以认为是一个资源
规则
规则就是用来定义如何进行保护资源的
作用在资源之上, 定义以什么样的方式保护资源,主要包括流量控制规则、熔断降级规则以及系统
保护规则。
我们入门案例中就是为message1资源设置了一种流控规则, 限制了进入message1的流量

2 重要功能

在这里插入图片描述
Sentinel的主要功能就是容错,主要体现为下面这三个:
流量控制
流量控制在网络传输中是一个常用的概念,它用于调整网络包的数据。任意时间到来的请求往往是
随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。
Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状。
熔断降级
当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则
对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。
Sentinel 对这个问题采取了两种手段:

  • 通过并发线程数进行限制
    Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。当某个资源
    出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆
    积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的
    线程完成任务后才开始继续接收请求。
  • 通过响应时间对资源进行降级
    除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。
    当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的
    时间窗口之后才重新恢复。
  • Sentinel 和 Hystrix 的区别
    两者的原则是一致的, 都是当一个资源出现问题时, 让其快速失败, 不要波及到其它服务
    但是在限制的手段上, 确采取了完全不一样的方法:
    Hystrix 采用的是线程池隔离的方式, 优点是做到了资源之间的隔离, 缺点是增加了线程
    切换的成本。
    Sentinel 采用的是通过并发线程的数量和响应时间来对资源做限制。
    系统负载保护
    Sentinel 同时提供系统维度的自适应保护能力。当系统负载较高的时候,如果还持续让
    请求进入可能会导致系统崩溃,无法响应。在集群环境下,会把本应这台机器承载的流量转发到其
    它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,Sentinel 提供了对应的保
    护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请
    求。
    总之一句话: 我们需要做的事情,就是在Sentinel的资源上配置各种各样的规则,来实现各种容错的功

6.7 Sentinel规则

1 流控规则

流量控制,其原理是监控应用流量的QPS(每秒查询率) 或并发线程数等指标,当达到指定的阈值时
对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

第1步: 点击簇点链路,我们就可以看到访问过的接口地址,然后点击对应的流控按钮,进入流控规则配
置页面。新增流控规则界面如下:
在这里插入图片描述
资源名:唯一名称,默认是请求路径,可自定义
针对来源:指定对哪个微服务进行限流,默认指default,意思是不区分来源,全部限制
阈值类型/单机阈值:

  • QPS(每秒请求数量): 当调用该接口的QPS达到阈值的时候,进行限流
  • 线程数:当调用该接口的线程数达到阈值的时候,进行限流
    是否集群:暂不需要集群
    接下来我们以QPS为例来研究限流规则的配置。
2 简单配置

我们先做一个简单配置,设置阈值类型为QPS,单机阈值为1。即每秒请求量大于3的时候开始限流。
接下来,在流控规则页面就可以看到这个配置
在这里插入图片描述

然后快速访问 /order/message1 接口,观察效果。此时发现,当QPS > 1的时候,服务就不能正常响
应,而是返回Blocked by Sentinel (flow limiting)结果。

在这里插入图片描述

3.配置流控模式

点击上面设置流控规则的编辑按钮,然后在编辑页面点击高级选项,会看到有流控模式一栏。
在这里插入图片描述
sentinel共有三种流控模式,分别是:

  1. 直接(默认):接口达到限流条件时,开启限流
  2. 关联:当关联的资源达到限流条件时,开启限流 [适合做应用让步]
  3. 链路:当从某个接口过来的资源达到限流条件时,开启限流
    下面呢分别演示三种模式:
    直接流控模式
    直接流控模式是最简单的模式,当指定的接口达到限流条件时开启限流。上面案例使用的就是直接流控
    模式。
    关联流控模式
    关联流控模式指的是,当指定接口关联的接口达到限流条件时,开启对指定接口开启限流。

链路流控模式
链路流控模式指的是,当从某个接口过来的资源达到限流条件时,开启限流。它的功能有点类似于针对
来源配置项,区别在于:针对来源是针对上级微服务,而链路流控是针对上级接口,也就是说它的粒度
更细

第1步: 编写一个service,在里面添加一个方法message

@Service
public class OrderServiceImplTest001 {
    @SentinelResource("message")
    public void message() {
        System.out.println("message");
    }
}

第2步: 在Controller中声明两个方法,分别调用service中的方法m

@RestController
@Slf4j
public class OrderControllerTest001 {

    @Autowired
    private OrderServiceImplTest001 orderServiceImplTest001;
    
    @RequestMapping("/order/message1")
    public String message1() {
        orderServiceImplTest001.message();
        return "message1";
    }

    @RequestMapping("/order/message2")
    public String message2() {
        orderServiceImplTest001.message();
        return "message2";
    }

}

第3步: 禁止收敛URL的入口 context
备注:如果使用的版本过低需要配置,如果是最新版本无需配置
从1.6.3 版本开始,Sentinel Web filter默认收敛所有URL的入口context,因此链路限流不生效。
1.7.0 版本开始(对应SCA的2.1.1.RELEASE),官方在CommonFilter 引入了
WEB_CONTEXT_UNIFY 参数,用于控制是否收敛context。将其配置为 false 即可根据不同的
URL 进行链路限流。
SCA 2.1.1.RELEASE之后的版本,可以通过配置spring.cloud.sentinel.web-context-unify=false即
可关闭收敛
我们当前使用的版本是SpringCloud Alibaba 2.1.0.RELEASE,无法实现链路限流。
目前官方还未发布SCA 2.1.2.RELEASE,所以我们只能使用2.1.1.RELEASE,需要写代码的形式实

配置文件中关闭sentinel的CommonFilter实例化

server:
  port: 8091
spring:
  application:
    name: service-order02
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.93.1:8848
    sentinel:
      transport:
        port: 9999 # 跟控制台交流的端口,随意指定一个未使用的端口即可
        dashboard: localhost:18080 #指定控制台服务的地址
      filter:
        enabled: false

添加一个配置类,自己构建CommonFilter实例

package com.itheima.config;
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FilterContextConfig {
@Bean
public FilterRegistrationBean sentinelFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new CommonFilter());
registration.addUrlPatterns("/*");
// 入口资源关闭聚合
registration.addInitParameter(CommonFilter.WEB_CONTEXT_UNIFY, "false");
registration.setName("sentinelFilter");
registration.setOrder(1);
return registration;
}
}

第4步:配置完重启服务。浏览器分别访问
http://localhost:8091/order/message1
http://localhost:8091/order/message2

第5步: 控制台配置限流规则

在这里插入图片描述
在这里插入图片描述
第6步: 分别通过 /order/message1 和 /order/message2 访问, 发现关联的接口资源被限流了
在这里插入图片描述

4 配置流控效果

快速失败(默认): 直接失败,抛出异常,不做任何额外的处理,是最简单的效果
Warm Up:它从开始阈值到最大QPS阈值会有一个缓冲阶段,一开始的阈值是最大QPS阈值的
1/3,然后慢慢增长,直到最大阈值,适用于将突然增大的流量转换为缓步增长的场景。
排队等待:让请求以均匀的速度通过,单机阈值为每秒通过数量,其余的排队等待; 它还会让设
置一个超时时间,当请求超过超时间时间还未处理,则会被丢弃。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1494361.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

00X集——CAD vba 填充(hatch)及挖空

首先&#xff0c;画个椭圆&#xff0c;并填充&#xff0c;直接上代码&#xff1a; Sub 画椭圆填充() 2024年3月6日21:10:22 by qq443440204 Dim hat As AcadHatch 填充 Dim ell(0) As AcadEllipse 椭圆 Dim cent(0 To 2) As Double 椭圆中心点 Dim dd(0 To 2) As Double 椭圆长…

Android开发手册,android面试试题

前言 组件化是 保持整个 App 可持续地进行高质量开发的基础&#xff0c;近年来也是业界一直在积极探索和实践的方向&#xff0c;在深入理解组件化架构的过程中&#xff0c;将不断考验你的技术深度与广度&#xff1b;实践中我还参考了十几家技术团队的解决方案&#xff08;例如…

智能设备 app 设计 —— 蓝蓝 UI 设计公司

今天给大家推荐是智能设备app设计&#xff0c;随着智能设备的逐渐普及随之操作app也越来越多&#xff0c;希望能给大家带来灵感 #日常灵感 #创意设计#UI提升#ui设计#app #设计案例分享|#设计 #产品设计#产品设计#设计灵感 #B端产品经理 #ui #产品 #美工 #交互 #产品经理 #开发 …

android实战视频教程,细数Android开发者的艰辛历程

缘起 随着互联网企业的不断发展&#xff0c;产品项目中的模块越来越多&#xff0c;用户体验要求也越来越高&#xff0c;想实现小步快跑、快速迭代的目的越来越难&#xff0c;还有应用之间的互相调用等等问题&#xff0c;插件化技术应用而生。如果没有插件化技术&#xff0c;美…

64位Office API声明语句第116讲

跟我学VBA&#xff0c;我这里专注VBA, 授人以渔。我98年开始&#xff0c;从源码接触VBA已经20余年了&#xff0c;随着年龄的增长&#xff0c;越来越觉得有必要把这项技能传递给需要这项技术的职场人员。希望职场和数据打交道的朋友&#xff0c;都来学习VBA,利用VBA,起码可以提高…

Qt插件之输入法插件的构建和使用(一)

文章目录 输入法概述输入法插件实现及调用输入键盘搭建定义样式自定义按钮实现自定义可拖动标签数字符号键盘候选显示控件滑动控件手绘输入控件输入法概述 常见的输入法有三种形式: 1.系统级输入法 2.普通程序输入法 3.程序自带的输入法 系统级输入法就是咱们通常意义上的输入…

普中51单片机学习(AD转换)

AD转换 分辨率 ADC的分辨率是指使输出数字量变化一个相邻数码所需输入模拟电压的变化量。常用二进制的位数表示。例如12位ADC的分辨率就是12位&#xff0c;或者说分辨率为满刻度的1/(2^12)。 一个10V满刻度的12位ADC能分辨输入电压变化最小值是10V1/(2^12 )2.4mV。 量化误差 …

C++ 哈希表OJ

目录 1、1. 两数之和 2、面试题 01.02. 判定是否互为字符重排 3、217. 存在重复元素 4、 219. 存在重复元素 II 5、49. 字母异位词分组 频繁查找某一个数的时候可以使用哈希表&#xff0c;哈希表可以使用容器&#xff0c;也可以使用数组模拟&#xff0c;当元素是字符串中的字…

8、Linux驱动开发:驱动-读写接口实现(readwrite)

目录 &#x1f345;点击这里查看所有博文 随着自己工作的进行&#xff0c;接触到的技术栈也越来越多。给我一个很直观的感受就是&#xff0c;某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了&#xff0c;只有经常会用到的东西才有可能真正记…

npm 私服以及使用

在工作中&#xff0c;公司有很多内部的包并不希望发布到npm官网仓库&#xff0c;因为可能涉及到一些私有代码不能暴露。对于前端来讲&#xff0c;这时就可以选择在公司内网搭建npm私有仓库。当前比较主流的几种解决方案&#xff1a;verdaccio、nexus、cnpm。大家可以按照自己的…

MongoDB Helloworld For Window

1. 下载MongoDB Download MongoDB Community Server | MongoDB 2. 安装MongoDB 3. 创建DB. 4. 用java code 连接mongo. 做增删改查操作。 pom.xml <dependency><groupId>org.mongodb</groupId><artifactId>mongodb-driver-sync</artifactId>&…

Frida-Hook-Java层操作大全

附件下载 https://github.com/DERE-ad2001/Frida-Labs 前期准备 使用 jadx 进行逆向工程的基础知识。应具备理解 Java 代码的能力。具备编写小型 JavaScript 代码片段的能力。熟悉 adb。设备已 root。Frida环境配置 Hook&#xff08;Hooking&#xff09;简介 让我们从非常…

IPsec VPN协议框架

IPsec是IETF&#xff08;Internet Engineering Task Force&#xff09;制定的一组开放的网络安全协议。它并不是一个单独的协议&#xff0c;而是一系列为IP网络提供安全性的协议和服务的集合&#xff0c;包括认证头AH&#xff08;Authentication Header&#xff09;和封装安全载…

dolphinscheduler海豚调度(五)seatunnel案例

seatunnel作为新一代流行的数据集成工具&#xff0c;其功能非常强大且简单易用&#xff0c;今天演示一下如何通过dolphinscheduler创建并运行seatunnel任务 本次dolphinscheduler和seatunnel均部署在同一机器上的单机版本 1、环境配置 打开dolphinscheduler安装目录&#xf…

【Python】新手入门(6):变量与数据类型

【Python】新手入门&#xff08;6&#xff09;&#xff1a;变量与数据类型 &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448…

Java多线程——synchronized、volatile 保障可见性

目录 引出synchronized、volatile 保障可见性Redis冲冲冲——缓存三兄弟&#xff1a;缓存击穿、穿透、雪崩缓存击穿缓存穿透缓存雪崩 总结 引出 Java多线程——synchronized、volatile 保障可见性 synchronized、volatile 保障可见性 原子性&#xff1a;在一次或者多次操作时…

嵌入式学习-FreeRTOS-Day1

一、重点 1、VCC和GND VCC&#xff1a; 1、电路中为电源&#xff0c;供应电压 2、3.3v-5v 3、数字信号中用1表示GND&#xff1a; 1、表示地线 2、一般为0v 3、数字信号中用0表示2、电容和电阻 电容 存储电荷 存储能量&#xff1a; 电容器可以在其两个导体板&#xff08;极…

03.axios数据提交和错误处理

一.axios常用请求方法和数据提交 1. 想要提交数据&#xff0c;先来了解什么是请求方法 请求方法是一些固定单词的英文&#xff0c;例如&#xff1a;GET&#xff0c;POST&#xff0c;PUT&#xff0c;DELETE&#xff0c;PATCH&#xff08;这些都是http协议规定的&#xff09;&am…

【Web】浅聊JDBC的SPI机制是怎么实现的——DriverManager

目录 前言 分析 前言 【Web】浅浅地聊JDBC java.sql.Driver的SPI后门-CSDN博客 上篇文章我们做到了知其然&#xff0c;知道了JDBC有SPI机制&#xff0c;并且可以利用其Driver后门 这篇文章希望可以做到知其所以然&#xff0c;对JDBC的SPI机制的来源做到心里有数 分析 先是…

开源玩具总动员-本博客的知识关系图

作为一个非全职编程爱好者&#xff0c;基本是把计算机周边当做高档大玩具来玩的&#xff0c;顺便带着有兴趣的学生搞一搞学习。这篇文章作为全站的一个导航篇&#xff0c;把本博客的主干要点汇聚一下。从小学开始一直与计算机结缘。通过各种业余时间&#xff0c;慢慢地把感兴趣…