【SpringCloud】07 流量管理sentinel

news2025/1/16 20:03:57

sentinel

Sentinel 是面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性。

1. 微服务中的服务雪崩

服务雪崩效应是一种因“服务提供者的不可用”(原因)导致“服务调用者不可用”(结果),并将不可用逐渐放大的现象。

2. 解决雪崩的方案

造成服务雪崩的原因有很多,包括硬件原因,网络原因,软件原因等等。这里,我们只谈从软件方面,解决服务雪崩的几种解决方案和解决套路,以此来了解微服务架构中相关的技术栈的由来以及使用理由。

设置超时:
造成线程的挤压都是因为同步远程调用长时间没有得到回复造成的,所以设置超时时间,可以减少线程的长时间占用,避免线程挤压。
流量限制:
对服务进行限流,避免服务因并发量过大而造成服务崩掉。
熔断降级:
对已经挂掉的服务,直接不再进行调用,而是直接返回结果,这就是熔断。以此避免已经挂掉的服务对调用者造成的影响。
舱壁模式:
舱壁模式(Bulkhead)隔离了每个工作负载或服务的关键资源,如连接池、内存和CPU。
使用舱壁 避免了单个工作负载(或服务)消耗掉所有资源,从而导致其他服务出现故障的场景。
这种模式主要是通过防止由一个服务引起的级联故障来增加系统的弹性。
泰坦尼克号沉没的主要原因之一是其舱壁设计失败,水可以通过上面的甲板倒在舱壁的顶部,导致整个船体淹没。

流量管理的主键:hystrix:netflix 和​ sentinel:阿里巴巴

3. 使用sentinel

开启sentinel控制台
可以设置接入该控制台的微服务的流量控制 熔断降级。
运行sentinel的jar包
在这里插入图片描述
访问控制台界面

http://localhost:8080
在这里插入图片描述
账户和密码: sentinel/sentinel

微服务接入sentinel平台
(1)引入依赖

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

(2)配置

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080

(3)访问微服务的任意接口
在这里插入图片描述

点击资源/order/{orderId}后面的流控按钮,就可以弹出表单。表单中可以添加流控规则,如下图所示:
在这里插入图片描述

其含义是限制 /order/{orderId}这个资源的单机QPS为1,即每秒只允许1次请求,超出的请求会被拦截并报错。

3.1 三种流控模式

在添加限流规则时,点击高级选项,可以选择三种流控模式:

  • 直接:统计当前资源的请求,触发阈值时对当前资源直接限流,也是默认的模式
  • 关联:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流
  • 链路:统计从指定链路访问到本资源的请求,触发阈值时,对指定链路限流

在这里插入图片描述

3.1.1 关联模式

关联模式:统计与当前资源相关的另一个资源,触发阈值时,对当前资源限流

  • 使用场景:比如用户支付时需要修改订单状态,同时用户要查询订单。查询和修改操作会争抢数据库锁,产生竞争。
    • 业务需求是有限支付和更新订单的业务,因此当修改订单业务触发阈值时,需要对查询订单业务限流。

在这里插入图片描述

当/write资源访问量触发阈值时,就会对/read资源限流,避免影响/write资源。

满足下面条件可以使用关联模式:

  • 两个有竞争关系的资源
  • 一个优先级较高,一个优先级较低

3.1.2 链路模式

链路模式:只针对从指定链路访问到本资源的请求做统计,判断是否超过阈值。

例如有两条请求链路:

  • /test1 -》 /common

  • /test2 -》 /common

如果只希望统计从/test2进入到/common的请求,则可以这样配置:
在这里插入图片描述

  • Sentinel默认只标记Controller中的方法为资源,如果要标记其它方法,需要利用@SentinelResource注解,示例:
  • Sentinel默认会将Controller方法做context整合,导致链路模式的流控失效,需要修改application.yml,添加配置:
    -

4. 流控效果

流控效果是指请求达到流控阈值时应该采取的措施,包括三种:

  • 快速失败:达到阈值后,新的请求会被立即拒绝并抛出FlowException异常。是默认的处理方式。
  • warm up:预热模式,对超出阈值的请求同样是拒绝并抛出异常。但这种模式阈值会动态变化,从一个较小值逐渐增加到最大阈值。
  • 排队等待:让所有的请求按照先后次序排队执行,两个请求的间隔不能小于指定时长

在这里插入图片描述

4.1 warm up

warm up也叫预热模式,是应对服务冷启动的一种方案。请求阈值初始值是 threshold / coldFactor,持续指定时长后,逐渐提高到threshold值。而coldFactor的默认值是3.

例如,我设置QPS的threshold为10,预热时间为5秒,那么初始阈值就是 10 / 3 ,也就是3,然后在5秒后逐渐增长到10.

在这里插入图片描述

4.2 排队等待

当请求超过QPS阈值时,快速失败和warm up 会拒绝新的请求并抛出异常。而排队等待则是让所有请求进入一个队列中,然后按照阈值允许的时间间隔依次执行。后来的请求必须等待前面执行完成,如果请求预期的等待时间超出最大时长,则会被拒绝。

例如:QPS = 5,意味着每200ms处理一个队列中的请求;timeout = 2000,意味着预期等待超过2000ms的请求会被拒绝并抛出异常
在这里插入图片描述

5. 热点参数限流

在这里插入图片描述
热点参数限流默认对SpringMVC资源无效

6. 熔断和降级

6.1 openfeign和sentinel整合

(1)开启feign的sentinel功能

# 开启openfeign的sentinel功能
feign:
  sentinel:
    enabled: true

(2)创建一个降级类并实现FallbackFactory接口 该接口的泛型就是feign接口类

@Component
@Slf4j
public class ProductFeignFactory implements FallbackFactory<ProductFeign>{
    @Override
    public ProductFeign create(Throwable throwable) {
        return new ProductFeign() {
            @Override
            public Product getById(Long pid) {
                log.error("商品微服务故障"+throwable.getMessage());
                //默认的一个商品对象
                Product product=new Product();
                return product;
            }
        };
    }
}

(3)在feign调用时使用降级类

//value:调用远程微服务的名称    fallbackFactory:降级类工厂
@FeignClient(value = "shop-product",fallbackFactory = ProductFeignFactory.class)
public interface ProductFeign {
    @GetMapping("/product/getById/{pid}")  
    public Product getById(@PathVariable Long pid);
}

6.2 线程隔离(舱壁模式)

在这里插入图片描述

在添加限流规则时,可以选择两种阈值类型:

  • QPS:就是每秒的请求数,在快速入门中已经演示过
  • 线程数:是该资源能使用用的tomcat线程数的最大值。也就是通过限制线程数量,实现舱壁模式。

线程隔离的两种手段是?

  • 信号量隔离

  • 线程池隔离

信号量隔离的特点是?

  • 基于计数器模式,简单,开销小

线程池隔离的特点是?

  • 基于线程池模式,有额外开销,但隔离控制更强

6.3 熔断降级

熔断降级是解决雪崩问题的重要手段。其思路是由断路器统计服务调用的异常比例、慢请求比例,如果超出阈值则会熔断该服务。即拦截访问该服务的一切请求;而当服务恢复时,断路器会放行访问该服务的请求。

在这里插入图片描述
断路器熔断策略有三种:慢调用、异常比例、异常数

  • 慢调用:业务的响应时长(RT)大于指定时长的请求认定为慢调用请求。在指定时间内,如果请求数量超过设定的最小数量,慢调用比例大于设定的阈值,则触发熔断。例如:
    在这里插入图片描述
    解读:RT超过500ms的调用是慢调用,统计最近10000ms内的请求,如果请求量超过10次,并且慢调用比例不低于0.5,则触发熔断,熔断时长为5秒。然后进入half-open状态,放行一次请求做测试。

  • 异常比例或异常数:统计指定时间内的调用,如果调用次数超过指定请求数,并且出现异常的比例达到设定的比例阈值(或超过指定异常数),则触发熔断。例如:
    在这里插入图片描述
    解读:统计最近1000ms内的请求,如果请求量超过10次,并且异常比例不低于0.5,则触发熔断,熔断时长为5秒。然后进入half-open状态,放行一次请求做测试。

Sentinel熔断降级的策略有哪些?

  • 慢调用比例:超过指定时长的调用为慢调用,统计单位时长内慢调用的比例,超过阈值则熔断

  • 异常比例:统计单位时长内异常调用的比例,超过阈值则熔断

  • 异常数:统计单位时长内异常调用的次数,超过阈值则熔断

7. sentinel定义持久化

上面写的那么多规则,当微服务客户端重启后,规则会丢失。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Sentinel的三种配置管理模式是什么?

  • 原始模式:保存在内存

  • pull模式:保存在本地文件或数据库,定时去读取,性能会低

  • push模式:保存在nacos,监听变更实时更新,目前企业比较推广的
    sentinle中nacos没有提供 需要你修改sentinel源码,修改后把源码打包为jar,重新启动该jar包。

7.1 pull模式

规则保证到本地文件
(1)定义持久化到文件中的类

package com.aaa.order.rule;

import com.alibaba.csp.sentinel.command.handler.ModifyParamFlowRulesCommandHandler;
import com.alibaba.csp.sentinel.datasource.*;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRule;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityRuleManager;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRuleManager;
import com.alibaba.csp.sentinel.slots.system.SystemRule;
import com.alibaba.csp.sentinel.slots.system.SystemRuleManager;
import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import org.springframework.beans.factory.annotation.Value;

import java.io.File;
import java.io.IOException;
import java.util.List;
//用于规则持久化到文件中
public class FilePersistence implements InitFunc {

    @Value("${spring.application.name}")
    private String appcationName;

    @Override
    public void init() throws Exception {
        String ruleDir =  "D:/sentinel-rules/shop-order" ;
        String flowRulePath = ruleDir + "/flow-rule.json";
        String degradeRulePath = ruleDir + "/degrade-rule.json";
        String systemRulePath = ruleDir + "/system-rule.json";
        String authorityRulePath = ruleDir + "/authority-rule.json";
        String paramFlowRulePath = ruleDir + "/param-flow-rule.json";

        this.mkdirIfNotExits(ruleDir);
        this.createFileIfNotExits(flowRulePath);
        this.createFileIfNotExits(degradeRulePath);
        this.createFileIfNotExits(systemRulePath);
        this.createFileIfNotExits(authorityRulePath);
        this.createFileIfNotExits(paramFlowRulePath);

        // 流控规则
        ReadableDataSource<String, List<FlowRule>> flowRuleRDS = new FileRefreshableDataSource<>(
                flowRulePath,
                flowRuleListParser
        );
        FlowRuleManager.register2Property(flowRuleRDS.getProperty());
        WritableDataSource<List<FlowRule>> flowRuleWDS = new FileWritableDataSource<>(
                flowRulePath,
                this::encodeJson
        );
        WritableDataSourceRegistry.registerFlowDataSource(flowRuleWDS);

        // 降级规则
        ReadableDataSource<String, List<DegradeRule>> degradeRuleRDS = new FileRefreshableDataSource<>(
                degradeRulePath,
                degradeRuleListParser
        );
        DegradeRuleManager.register2Property(degradeRuleRDS.getProperty());
        WritableDataSource<List<DegradeRule>> degradeRuleWDS = new FileWritableDataSource<>(
                degradeRulePath,
                this::encodeJson
        );
        WritableDataSourceRegistry.registerDegradeDataSource(degradeRuleWDS);

        // 系统规则
        ReadableDataSource<String, List<SystemRule>> systemRuleRDS = new FileRefreshableDataSource<>(
                systemRulePath,
                systemRuleListParser
        );
        SystemRuleManager.register2Property(systemRuleRDS.getProperty());
        WritableDataSource<List<SystemRule>> systemRuleWDS = new FileWritableDataSource<>(
                systemRulePath,
                this::encodeJson
        );
        WritableDataSourceRegistry.registerSystemDataSource(systemRuleWDS);

        // 授权规则
        ReadableDataSource<String, List<AuthorityRule>> authorityRuleRDS = new FileRefreshableDataSource<>(
                authorityRulePath,
                authorityRuleListParser
        );
        AuthorityRuleManager.register2Property(authorityRuleRDS.getProperty());
        WritableDataSource<List<AuthorityRule>> authorityRuleWDS = new FileWritableDataSource<>(
                authorityRulePath,
                this::encodeJson
        );
        WritableDataSourceRegistry.registerAuthorityDataSource(authorityRuleWDS);

        // 热点参数规则
        ReadableDataSource<String, List<ParamFlowRule>> paramFlowRuleRDS = new FileRefreshableDataSource<>(
                paramFlowRulePath,
                paramFlowRuleListParser
        );
        ParamFlowRuleManager.register2Property(paramFlowRuleRDS.getProperty());
        WritableDataSource<List<ParamFlowRule>> paramFlowRuleWDS = new FileWritableDataSource<>(
                paramFlowRulePath,
                this::encodeJson
        );
        ModifyParamFlowRulesCommandHandler.setWritableDataSource(paramFlowRuleWDS);
    }

    private Converter<String, List<FlowRule>> flowRuleListParser = source -> JSON.parseObject(
            source,
            new TypeReference<List<FlowRule>>() {
            }
    );
    private Converter<String, List<DegradeRule>> degradeRuleListParser = source -> JSON.parseObject(
            source,
            new TypeReference<List<DegradeRule>>() {
            }
    );
    private Converter<String, List<SystemRule>> systemRuleListParser = source -> JSON.parseObject(
            source,
            new TypeReference<List<SystemRule>>() {
            }
    );

    private Converter<String, List<AuthorityRule>> authorityRuleListParser = source -> JSON.parseObject(
            source,
            new TypeReference<List<AuthorityRule>>() {
            }
    );

    private Converter<String, List<ParamFlowRule>> paramFlowRuleListParser = source -> JSON.parseObject(
            source,
            new TypeReference<List<ParamFlowRule>>() {
            }
    );

    private void mkdirIfNotExits(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }
    }

    private void createFileIfNotExits(String filePath) throws IOException {
        File file = new File(filePath);
        if (!file.exists()) {
            file.createNewFile();
        }
    }

    private <T> String encodeJson(T t) {
        return JSON.toJSONString(t);
    }
}

(2)添加配置
在resources下创建配置目录 META-INF/services ,然后添加文件

com.alibaba.csp.sentinel.init.InitFunc

在文件中添加配置类的全路径

com.aaa.rule.FilePersistence
在这里插入图片描述

7.2 push模式

push到配置中心nacos
sentinel 的持久化,我们希望这样:

  • 可以在 sentinel 控制台中编辑 限流配置,并且同步到 nacos 做持久化
  • 在 nacos 中修改了限流配置,也可以同步到 sentinel 控制台

要实现上述第一个功能需要对 sentinel 控制台的源码有所了解,并加依改造。

但 GitHub 上已经有人改造好了,做了个加强版控制台。

https://github.com/CHENZHENNAME/sentinel-dashboard-nacos

7.2.1 修改sentinel

  1. 打开上述网址 下载到本地
    在这里插入图片描述
  2. 解压上面的文件:
    在这里插入图片描述
  3. 打开根目录下的 pom.xml ,修改 sentinel 的版本
    在这里插入图片描述
  4. 进入项目根目录,cmd,执行命令 mvn clean package
    在这里插入图片描述
  5. 打包后生产在target目录下
    在这里插入图片描述
  6. 执行命令,启动控制台:

java -Dserver.port=8080 -Dnacos.serverAddr=localhost:8848 -jar sentinel-dashboard.jar


-Dserver.port 控制台端口号
-Dnacos.serverAddr: nacos 地址
-Dnacos.namespace: 你项目所在的 nacos 命名空间 如果命名空间就是public可以省略该参数
在这里插入图片描述
在这里插入图片描述

7.2.2 微服务客户端接入sentinel控制面板

  1. 引入依赖
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
    <version>1.8.1</version>
</dependency>
  1. 修改配置文件
    在这里插入图片描述

启动微服务

然后浏览器访问:http://localhost:8080 , 最开始什么都没有,然后访问你自己的项目的任意一个要限流的接口,则 左侧会出现对于的 服务名称
在这里插入图片描述
点击 簇点链路,新增 一个流控规则:
在这里插入图片描述
注意,一定要点 带 2 的,只有带 2 的才能推送到 nacos,在 流控规则 选项中添加也不行,只能点击 蓝色方框 才能推送到 nacos
在这里插入图片描述

添加成功后,nacos 中,你指定的命名空间下会自动生成 ${application-name}-flow-rules 格式的配置文件
在这里插入图片描述
当你在 sentinel 控制台中,无论增加规则,还是修改规则,都会同步到 nacos;相反,修改 nacos 中 配置文件的限流规则,也会同步到 sentinel 。

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

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

相关文章

Springboot系列(二十二):如何纯文本转成.csv格式文件?|超级详细,建议收藏

一、前言&#x1f525; 不知道大家有咩有遇到这么个需求&#xff0c;给你一长串文本&#xff0c;要求你能导成excel格式展示数据&#xff0c;一时间我陷入了沉思&#xff0c;如果要常规转excel&#xff0c;最明显的一点就是固定表头名&#xff0c;然而并不是&#xff0c;这表头…

[附源码]计算机毕业设计springboot冬奥资讯系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【DL with Pytorch】第 2 章 : 神经网络的构建块

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

第一个Shader Graph

上篇我们用ShaderLab来实现了第一个Shader,但对于初学者也太复杂了,那有没有简单的方式来实现shader的操作呢? 现在我们来分享下ShaderGraph,可视化编程,如图所示 ShaderGraph介绍 ShaderGraph是2018年推出的,可以看下官网出的例子https://github.com/UnityTechnologi…

[Linux] 进程程序替换之实现一个简单的shell

进程程序替换替换原理替换函数实现一个简单的shell主要过程实现代码替换原理 用fork创建子进程后执行的是和父进程相同的程序&#xff0c;若要执行不同的代码分支&#xff0c;子进程往往要调用一种exec函数以执行另一个程序&#xff1b;当进程调用一种exec函数时&#xff0c;该…

信息论与编码:随参信道特性

文章目录随参信道数学模型的建立随参信道对信号传输的影响平坦性衰落及频率选择性衰落1.平坦性衰落Rayleigh 分布Rice 分布2.频率选择性衰落多径随参信道的时延扩展与相干带宽随参信道的多径时延特性多径信道的频域特性移动信道的多普勒扩展及相干时间1.多普勒扩展2.信道的相干…

nodejs大前端从入门到精通一

一、nodejs架构 nodejs核心组成Natives Modules 当前层内容由JS实现提供应用程序可直接调用库&#xff0c;例如fs、path、http等JS语文无法直接操作底层硬件设置 在和硬件交互的的桥梁&#xff0c;通过Builtin Modules(胶水层) 底层&#xff1a; V8&#xff1a;执行JS代码&…

Android——Theme和Style-由浅入深,全面讲解

1、官方详细解读 样式和主题背景 | Android 开发者 | Android Developers 2、应用场景 类似web设计中css样式。将应用设计的细节与界面的结构和行为分开。 样式style &#xff1a;应用于 单个 View 的外观。样式可以指定字体颜色、字号、背景颜色等属性 主题theme&…

【仿牛客网笔记】项目发布与总结——单元测试、项目监控

在项目上线之前需做好单元测试&#xff0c;平时开发的过程中&#xff0c;每个功能也需要进行单元测试。 验证注解的作用&#xff0c;注解是修饰方法的。 每次调方法都是静态的 对test1和test2分别进行运行 通过类进行运行&#xff0c;运行所有的方法 测试帖子的Service&#x…

【序列召回推荐】(task5)多兴趣召回Comirec-DR

note&#xff1a; 多兴趣召回建模。Comirec论文中的提出的第一个模型&#xff1a;Comirec-DR&#xff08;DR就是dynamic routing&#xff09;&#xff0c;阿里将用户行为序列的item embeddings作为初始的capsule&#xff0c;然后提取出多个兴趣capsules&#xff0c;即为用户的…

【Java】博客系统——详细解释+代码+详细注释(课设必过)

目录 前言 博客系统简要分析 一、数据库的设计 1.1 分析 1.2 代码实现&#xff08;创建数据库和表&#xff09; 二、封装数据库&#xff08;JDBC代码的编写&#xff09; 2.1、首先通过创建Maven项目&#xff0c;基于Small Tomcat部署 servlet&#xff1b; 2.2、封装数据…

telnet配置设备远程管理—eNSP

案例&#xff1a;给路由器配置远程管理&#xff0c;使一台路由器远程管理另一台。 所需设备&#xff1a;两台路由器&#xff0c;一根网线 图示 一、给两台设备配置IP地址 AR1&#xff08;以下命令&#xff09; a. sy b. int g0/0/0 c. ip add 1.1.1.1 24AR2 a. sy b. int g0/0…

区间信息维护与查询【线段树 】 - 原理1 线段树的基本操作

区间信息维护与查询【线段树 】 - 原理1 线段树的基本操作 线段树&#xff08;segment tree&#xff09;是一种基于分治思想的二叉树&#xff0c;它的每个节点都对应一个[L , R ]区间&#xff0c;叶子节点对应的区间L R 。每一个非叶子节点[L , R ]其左子节点的区间都为[L , (…

进程与线程的区别及联系

目录 1. 操作系统功能简介 2. 进程 2.1 认识进程 2.2 进程操作系统中如何管理 2.3 PCB如何描述 2.3.1 pid 2.3.2 内存指针 2.3.3 文件描述符表 2.3.4 进程调度相关属性 3. 内存管理 4. 线程 4.1 认识线程 4.2 进程与线程的关系 4.3 线程安全问题 1.操作系统功能简…

[附源码]计算机毕业设计springboot电子相册管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Git 入门 拉取仓库和推送仓库

目录 基本操作 本地建立仓库并推送到远端仓库 关联仓库失败 解决方法 从远端仓库拉取文件到本地 私有的仓库的连接 修改 提交者名称 IDEA/Pycharm等如何使用git 如何关闭git 功能 Git操作主要分为两类 &#xff0c;如何把自己建的项目同步的网上的仓库&#xff0c;如何…

OpenHarmony编译系统

GN 简介 直接百度 GN 入门 可以参考下面的示例&#xff0c;作为入门参考学习https://blog.csdn.net/weixin_44701535/article/details/88355958https://gn.googlesource.com/gn//main/docs/reference.mdhttps://chromium.googlesource.com/chromium/src/tools/gn//48062805e…

Java项目_在线点餐系统(jsp+sevlet+mysql)(含论文)

在线点餐系统(jspsevletmysql一、系统介绍二、功能展示1.主页(用户)2.菜单(用户)3.用户注册(用户)4.用户登陆(用户)5.我的订单(用户)6.餐桌管理(管理员)7.菜系管理(管理员)8.菜品管理(管理员)9.订单管理(管理员)三、获取源码一、系统介绍 系统主要功能&#xff1a; 用户&#…

4位资深专家多年大厂经验分享出Flink技术架构设计与实现原理

时间飞逝&#xff0c;转眼间毕业七年多&#xff0c;从事 Java 开发也六年了。我在想&#xff0c;也是时候将自己的 Java 整理成一套体系。 这一次的知识体系面试题涉及到 Java 知识部分、性能优化、微服务、并发编程、开源框架、分布式等多个方面的知识点。 写这一套 Java 面试…

bootstrap下拉菜单学习(五)

组件&#xff1a;下拉菜单 bootstrap字体图标和下拉菜单组件的使用 这些图标都存在我们引入的font文件夹内&#xff1a; 复制bootstrap所用的包&#xff1a; 创建html页面&#xff1a; 图标不仅可以直接放文本里面&#xff0c; 还可有结合按钮去用。 要使用组件&#xff1a;不…