【Spring Cloud Alibaba】(四)Dubbo框架介绍 及 整合Dubbo和OpenAI实战【文末附源码】

news2024/12/27 13:39:16

CSDN成就一亿技术人

系列目录

【Spring Cloud Alibaba】(一)微服务介绍 及 Nacos注册中心实战
【Spring Cloud Alibaba】(二)微服务调用组件Feign原理+实战
【Spring Cloud Alibaba】(三)OpenFeign扩展点实战 + 源码详解


本文目录

  • 系列目录
  • 前言
  • Spring Cloud与Dubbo的关系
  • Dubbo架构
  • 一、项目说明
  • 二、新建父工程gg-parent
    • 1. pom.xml 依赖
  • 二、API接口包 gg-api
    • 1. 数据传输对象DTO
    • 2. 接口服务Service
    • 3. pom.xml 依赖
  • 三、服务提供方 gg-chatgpt
    • 1. pom.xml 依赖
    • 2. application.properties
    • 3. 接口实现类ChatGPTServiceImpl
    • 4. 启动类ChatGPTRunner
  • 四、服务消费方 gg-entry
    • 1. pom.xml 依赖
    • 2. application.properties
    • 3. 测试类EntryController
    • 4. 启动类EntryRunner
  • 五、启动验证
    • 1. 先运行Nacos-server
    • 2. 验证调用
  • 六、常见问题
    • 1. 主要排查点
  • 总结


前言

从本文开始,我们将探讨在Spring Cloud Alibaba微服务组件中的另一个主打高性能RPC调用的微服务调用组件,也就是由阿里巴巴开源的,后捐献给了Apache基金会的Dubbo。在服务调用方面,Dubbo的用户体验无疑是极致的。借助Spring Cloud Alibaba项目,我们只需要几个小小的注解,便能在分分钟内搭建完成服务调用,这是否令你惊讶?简单而爽快!

本文会先从Spring Cloud与Dubbo的关系说起,再讲到Dubbo架构,然后实战落地!最后的常见问题排查绝对是新手必看!我敢说整合Dubbo时有 99% 的人会遇到!文末附源码!!!也有投票期待你的参与!

对于如何在Spring Cloud Alibaba中快速集成Apache Dubbo,我们会搭建一个全新的环境,这样你还可以复习一下Spring Cloud Alibaba环境搭建知识,并能同时在案例中学会如何调用OpenAI API 生成图片!

没有什么比图更直观的了,老哥准备了这张图,相信你能轻松对Dubbo远程调用有个大概的认识!
本地调用 VS Dubbo远程调用


Spring Cloud与Dubbo的关系

你是否见过下面这两类文章?

  • Spring Cloud 与 Dubbo的区别、对比、优缺点
  • Spring Cloud 整合 Dubbo

你心中是否有过 疑问:两个框架能拿来做对比, 说明是同类框架, 为什么又能做整合?

实际上,Apache Dubbo官方定位的是一款微服务框架,如下图,因此它和Spring Cloud都属于微服务框架,也都存在自己独特的生态系统,所以同作为微服务框架,它们经常拿来做对比
Apache Dubbo官网描述

另外,Dubbo最初的核心就是高性能 RPC 通信 和 自动服务发现,因此它在RPC服务调用方面做的很独立和强大,所以它又可以独立作为微服务调用组件被整合到Spring Cloud中,这就是为什么它们又能做整合!

综上,Dubbo既能与Spring Cloud相提并论,又能与Spring Cloud相辅相成!


Dubbo架构

对于Spring Cloud整合Dubbo,我们不看Dubbo的微服务架构,主要看它 服务发现、服务调用的架构,如下图:

Dubbo架构图

主要是四方的关系:

  • Registry(注册中心)
  • Provider(服务提供方:暴露服务)
  • Consumer(服务消费方,调用Provider服务)
  • Monitor (监控中心,可以暂不关注)

主要干了这5件事:

  • 0.start :提供方(Provider)先启动 -初始化
  • 1.register:提供方(Provider)注册 -初始化
  • 2.suscribe:消费方(Consumer)订阅服务提供方 -初始化
  • 3.notify:消费方收到订阅通知 -异步
  • 4.invoke:消费方调用提供方 -同步
  • 5.count, 即监控中心统计调用数据 -异步

然后我们就可以愉快的开始实战了,Let’s Go!


一、项目说明

  • 项目背景

2023-02-16周四晚,在《直达CSDN–当开发者遇到AIGC》的直播中,王总描述自己有一个比较深刻的案例,就是我把百度的文心一格AI生成图片的一些服务给到传统行业的人,他们用完之后非常震撼,因为传统行业他们需要图片的话需要请专业的人来做,可能一张图片需要几天的时间,如果用AI来生成的话,只要你把自己的需求描述清楚,可能几秒就能够生成出来,并且出来的效果非常精美,这是对传统行业的影响。

引自凉哥(几何心凉)的文章:CSDN城市开发者联盟、C友会期待你的加入 ,推荐阅读!

所以,我们就以实现AI作图为例,看看在微服务项目中我是怎么设计的!

  • 项目名: gg

设定需求:用户入驻后,使用OpenAI结合 [用户昵称地域兴趣爱好] 为用户生成[个性头像]!

仅以此抛砖引玉,你可以设计的更丰满!

  • 服务提供方(Provider),服务名:gg-chatgpt

提供OpenAI能力的服务!这里用OpenAI生成个性头像!

  • 服务消费方(Consumer),服务名:gg-entry

提供入驻能力的服务,会调用gg-chatgpt服务

  • 最终的项目结构如下图(大家可以先尝试自己搭建下):
    Dubbo实战框架整体预览

提前说明:服务的身份是相对的,服务提供方也可能是服务消费方。主要取决于微服务的拆分!

所以项目命名一般不会出现provider或consumer的关键词!


二、新建父工程gg-parent

对于Spring Cloud Alibaba的版本选择,第一篇已经有详细的说明,所以本篇对版本选择不变!

注册中心依然是使用标配的Nacos,对于Nacos-server的安装请参见第一篇:【Spring Cloud Alibaba】(一)微服务介绍 及 Nacos注册中心实战

对于dubbo的版本,spring-cloud-alibaba 2.2.7默认集成的是2.7.13,这里升级到2.7.18,主要是做了安全升级!

1. pom.xml 依赖

父工程只有一个pom.xml文件,主要目的是引入BOM,定义好版本,服务不必关心版本号,pom.xmldependencyManagement配置如下(内有详细注释):

<properties>
    <maven.compiler.source>8</maven.compiler.source>
    <maven.compiler.target>8</maven.compiler.target>
    <spring-boot.version>2.3.12.RELEASE</spring-boot.version>
    <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
    <spring-cloud-alibaba.version>2.2.7.RELEASE</spring-cloud-alibaba.version>
    <spring.version>5.2.21.RELEASE</spring.version>
    <dubbo.version>2.7.18</dubbo.version>
</properties>

<dependencyManagement>
    <dependencies>
        <!-- bom start -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-framework-bom</artifactId>
            <version>${spring.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- duboo-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-bom</artifactId>
            <version>${dubbo.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- spring cloud alibab-->
        <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>
        <!-- spring boot-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>${spring-boot.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- spring cloud-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
        <!-- bom end -->
        
        <!-- dubbo start -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <!-- dubbo end -->
        
        <!-- API start-->
        <dependency>
            <groupId>com.tiangang</groupId>
            <artifactId>gg-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!-- API end -->
    </dependencies>
</dependencyManagement>

二、API接口包 gg-api

API接口包,是实现RPC通信的接口定义,可以使API接口更加清晰,便于维护与管理,在OpenFeign实战中我也同样推荐过:API接口单独放在一个包里。

1. 数据传输对象DTO

  • 接口参数DTO,这里为了方便直接用了lombok
@Data
public class ChatGPTParamDTO implements Serializable {
    private String name;
    private String area;
    private String hobby;
}
  • 接口返回结果DTO
@Data
public class ChatGPTResultDTO implements Serializable {
    private String imageUrl;
}

2. 接口服务Service

public interface ChatGPTService {
	/**
     * 生成头像
     */
    ChatGPTResultDTO generateAvatar(ChatGPTParamDTO paramDTO);
}

3. pom.xml 依赖

lombok依赖是可选的,如果你不用,就没有依赖了!

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

三、服务提供方 gg-chatgpt

首先,新建一个SpringBoot程序,命名:gg-chatgpt

然后,在此基础上,主要实现

  • 注册到Nacos
  • 调用gg-chatgpt的Dubbo服务

1. pom.xml 依赖

  • spring-cloud-starter-alibaba-nacos-discovery:用于支持Nacos
  • spring-cloud-starter-dubbo:用于支持dubbo
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Dubbo Spring Cloud Starter -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-dubbo</artifactId>
    </dependency>
    <!-- Spring Cloud Nacos Service Discovery -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!-- API接口包 -->
    <dependency>
        <groupId>com.tiangang</groupId>
        <artifactId>gg-api</artifactId>
    </dependency>
</dependencies>

2. application.properties

# 服务端口
server.port=8081
# 注册中心的服务名
spring.application.name=gg-chatgpt
# 注册中心地址
spring.cloud.nacos.discovery.server-addr=localhost:8848

# dubbo协议
dubbo.protocols.dubbo.name = dubbo
# dubbo协议端口( ‐1 表示自增端口,从 20880 开始)
dubbo.protocols.dubbo.port = -1
# 其它dubbo配置先不关心

# openAI配置
chatgpt.image.generation.url=https://api.openai.com/v1/images/generations
chatgpt.secret=YOUR_KEY_SECRET

3. 接口实现类ChatGPTServiceImpl

这里主要是实现gg-api接口包的ChatGPTService,增加@DubboService注解,用于暴露Dubbo服务.

内部使用RestTemplate以HTTP方式调用OpenAI API生成图片.

对于RestTemplate的用法,建议看我的博文:RestTemplate.exchange各种用法(包括泛型等 --全)

当然,也可以使用OpenFeign以RPC方式调用OpenAI API生成图片.

对于OpenFeign实战案例,建议看我的博文:【Spring Cloud Alibaba】(二)微服务调用组件Feign原理+实战

@DubboService
public class ChatGPTServiceImpl implements ChatGPTService {

    @Value("${chatgpt.image.generation.url}")
    private String imageGenerationUrl;
    @Value("${chatgpt.secret}")
    private String secret;

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public ChatGPTResultDTO generateAvatar(ChatGPTParamDTO paramDTO) {
        ChatGPTResultDTO resultDTO = new ChatGPTResultDTO();
        resultDTO.setImageUrl(createImage(paramDTO));
        return resultDTO;
    }

    private String createImage(ChatGPTParamDTO paramDTO) {
        String prompt = String.format("生成一张个性头像: 昵称:%s, 地区:%s, 爱好:%s"
                , paramDTO.getName(), paramDTO.getArea(), paramDTO.getHobby());
        return invokeChatgptCreateImage(prompt);
    }

    private String invokeChatgptCreateImage(String prompt) {
        Map<String, Object> body = new HashMap<>();
        body.put("prompt", prompt);
        body.put("n", 1);
        body.put("size", "256x256");

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("Authorization", "Bearer " + secret);

        HttpEntity<?> httpEntity = new HttpEntity<>(body, headers);
        try {
            JSONObject responseBody = restTemplate.exchange(imageGenerationUrl, HttpMethod.POST, httpEntity, JSONObject.class).getBody();
            System.out.println(responseBody);
            if (responseBody != null && responseBody.get("data") != null) {
                return responseBody.getJSONArray("data").getJSONObject(0).get("url").toString();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "https://blog.csdn.net/scm_2008/article/details/128931945";
    }
}

4. 启动类ChatGPTRunner

额外增加注解:

  • @EnableDiscoveryClient 用于服务注册和发现
  • @EnableDubbo 用于扫描上面配置的@DubboService注解,scanBasePackages指定扫描的路径
@SpringBootApplication
@EnableDiscoveryClient
@EnableDubbo(scanBasePackages = {"com.tiangang.gg.chatgpt.facade"})
public class ChatGPTRunner {
    public static void main(String[] args) {
        SpringApplication.run(ChatGPTRunner.class, args);
    }
    
    @Configuration
    public class Config {
        @Bean
        public RestTemplate restTemplate(ClientHttpRequestFactory factory) {
            return new RestTemplate(factory);
        }

        @Bean
        public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
            SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
            factory.setConnectTimeout(15000);
            factory.setReadTimeout(30000);
            return factory;
        }
    }
}

四、服务消费方 gg-entry

首先,新建一个SpringBoot程序,命名:gg-entry

然后,在此基础上,主要实现

  • 注册到Nacos
  • 调用gg-chatgpt的Dubbo服务

1. pom.xml 依赖

  • spring-cloud-starter-alibaba-nacos-discovery:用于支持Nacos

  • spring-cloud-starter-dubbo:用于支持dubbo

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Dubbo Spring Cloud Starter -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-dubbo</artifactId>
    </dependency>
    <!-- Spring Cloud Nacos Service Discovery -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
    <!-- API接口包 -->
    <dependency>
        <groupId>com.tiangang</groupId>
        <artifactId>gg-api</artifactId>
    </dependency>
</dependencies>

2. application.properties

额外增加dubbo.cloud.subscribed-services = gg-chatgpt ,可以订阅多个提供方服务,以逗号分隔

# 服务端口
server.port=8082
# 注册中心的服务名
spring.application.name=gg-entry
# 注册中心地址
spring.cloud.nacos.discovery.server-addr=localhost:8848
# 订阅服务提供方
dubbo.cloud.subscribed-services = gg-chatgpt
# dubbo协议
dubbo.protocols.dubbo.name = dubbo
# dubbo协议端口( ‐1 表示自增端口,从 20880 开始)
dubbo.protocols.dubbo.port = -1
# 其它dubbo配置先不关心

3. 测试类EntryController

对于服务调用,通常都会在Service层调Dubbo服务,我这里简化只创建Controller,直接在Controller里调用Dubbo服务,目的就是为了测试验证,主要通过@DubboReference 引入dubbo服务

  • 注意这里不能@Autowired
  • retries:防止幂等问题设置为0:不重试
  • timeout: 防止调用服务超时,默认1秒,单位ms
@RestController
@RequestMapping("/entry")
public class EntryController {

    @DubboReference(retries = 0, timeout = 10000)
    private ChatGPTService chatGPTService;

    // 定义一个测试用的接口
    @PostMapping("/chatgpt")
    public ChatGPTResultDTO generateAvatar(@RequestBody ChatGPTParamDTO paramDTO) {
        return chatGPTService.generateAvatar(paramDTO);
    }
}

4. 启动类EntryRunner

额外增加注解:

  • @EnableDiscoveryClient 用于服务注册和发现
@SpringBootApplication
@EnableDiscoveryClient
public class EntryRunner {
    public static void main(String[] args) {
        SpringApplication.run(EntryRunner.class, args);
    }
}

五、启动验证

1. 先运行Nacos-server

cmd启动nacos

2. 验证调用

注意启动顺序:先启动服务提供者gg-chatgpt,再启动服务消费者gg-entry

启动后,到Nacos的服务列表,可以看到:
Nacos服务列表

使用postman测试一下,达到预期~ 💪💪💪
在这里插入图片描述

看看结果哈,这是画吗?也太真了,反正我是看不出来 这是真人照片还是AI的画了…
openAI生成图片


六、常见问题

初学者最常见的问题,也是最让人懵圈的报错:

No provider available from registry localhost:9090 for service xxx

1. 主要排查点

  1. 服务消费方(Consumer)是否正确订阅

    本例中就是:dubbo.cloud.subscribed-services=gg-chatgpt

    检查application.properties,有没有配置该项,或者配的对不对!

  2. 服务提供方(Provider)是否正确启用Dubbo

    本例中就是:@EnableDubbo(scanBasePackages = {"com.tiangang.gg.chatgpt.facade"})

    检查启动类上是否有@EnableDubbo注解,或者scanBasePackages的包路径(@DubboService所在包)配的对不对!

  3. 服务提供方(Provider)有没有启动!

    这也是为什么让你注意启动顺序的原因。


总结

最后,我再总结一下主要步骤,其实和本地调用相比,无外乎就是几个注解和配置的区别!

  • 提供方
  1. @DubboService声明提供方的服务,与本地服务声明用@Service对应
  2. 提供方在启动类上加@@EnableDubbo注解,提供DubboService
  • 消费方
  1. @DubboReference引入提供方的服务,与本地服务引入用@Autowired对应
  2. 消费方用dubbo.cloud.subscribed-services配置,订阅DubboService

如果你能看懂我总结的这几点,那么恭喜你,说明你对Dubbo基础应用入门了!

img
源码下载地址:https://download.csdn.net/download/scm_2008/87467404
对于Dubbo,你知道他有哪些坑吗?这也是我计划将在下文分享的内容,如果感觉不错,欢迎订阅本专栏,后面还有更多的【Spring Cloud Alibaba】实战知识陆续放出。

关注我 天罡gg 分享更多干货: https://blog.csdn.net/scm_2008
大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!

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

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

相关文章

干货| 三大软件架构对比与分析

从系统的组织和部署结构方面来看&#xff0c;软件架构的演化进程显然有着从简单到复杂的趋势。那是否最新最复杂的架构就是目前业界选择的最佳架构呢&#xff1f;非也。没有最好的架构&#xff0c;只有最合适的架构。在软件架构的选择上&#xff0c;“合适”比“新”更加重要。…

11.注意力机制

11.注意力机制 目录 注意力提示 查询、键和值 注意力的可视化 注意力汇聚&#xff1a;Nadaraya-Watson 核回归 生成数据集 非参注意力池化层 Nadaraya-Watson核回归 参数化的注意力机制 批量矩阵乘法 定义模型 训练 注意力评分函数 掩蔽softmax操作 加性注意力 缩…

家政服务小程序实战开发教程015-填充用户信息

我们上一篇讲解了立即预约功能&#xff0c;存在的问题是&#xff0c;每次都需要用户填写联系信息。在我们前述篇章中已经介绍了用户注册的功能&#xff0c;在立即预约的时候我们需要把已经填写的用户信息提取出来&#xff0c;显示到表单对应的字段中。本篇我们就讲解一下如何提…

K8S+Jenkins+Harbor+Docker+gitlab集群部署

K8SJenkinsHarborDockergitlab服务器集群部署 目录K8SJenkinsHarborDockergitlab服务器集群部署1.准备以下服务器2.所有服务器统一处理执行2.1 关闭防火墙2.2 关闭selinux2.3 关闭swap&#xff08;k8s禁止虚拟内存以提高性能&#xff09;2.4 更新yum (看需要更新)2.5 时间同步2…

【自监督论文阅读笔记】MVP: Multimodality-guided Visual Pre-training

Abstract 最近&#xff0c;掩码图像建模&#xff08;MIM&#xff09;已成为视觉预训练的一个有前途的方向。在vision transformers的上下文中&#xff0c;MIM 通过将 token-level 标记级特征 与 预定义空间 对齐来学习有效的视觉表示&#xff08;例如&#xff0c;BEIT 使用在大…

03- 通过OpenCV进行图像变换 (OpenCV基础) (机器视觉)

知识重点 resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) 图像的放大与缩小, 变形 flip(src, flipCode) 图像的翻转 rotate(img, rotateCode) 图像的旋转 warpAffine(src, M, dsize, flags, mode, value) 仿射变换是图像旋转, 缩放, 平移的总称.具体的做法是通…

第四次作业

学生表&#xff1a;Student (Sno, Sname, Ssex , Sage, Sdept)学号&#xff0c;姓名&#xff0c;性别&#xff0c;年龄&#xff0c;所在系 Sno为主键课程表&#xff1a;Course (Cno, Cname)课程号&#xff0c;课程名 Cno为主键学生选课表&#xff1a;SC (Sno, Cno, Score)学号&…

九龙证券|豪掷超6000万,10转3派6元,今年第二只高送转股出炉!

新瀚新材高送转发布计划&#xff0c;股价年初以来大涨超50%。航运板块6股自2022年低点股价翻倍。 2月17日晚间&#xff0c;凯瑞德、新瀚新材2家公司发布了2022年年报&#xff1b;一起&#xff0c;新瀚新材高送转计划同步出炉。 报告显现&#xff0c;2022年度新瀚新材营业总收入…

软件测试简单面试

文章目录软件程序数据(库)文档服务 程序&#xff1a;完成预定功能、性能的可执行的指令操作信息的数据结构描述程序的操作和使用的文档 软件测试&#xff1a;使用技术手段来验证软件是否满足需求 软件质量&#xff1a; 满足软件需求&#xff0c;软件需求是度量软件质量的基础不…

尚医通 (十九)用户认证

目录一、对象存储OSS1、开通“对象存储OSS”服务2、创建Bucket3、上传默认头像4、创建RAM用户5、使用SDK二、后端集成OSS1、新建云存储微服务2、实现文件上传接口三、用户认证功能1、用户认证需求分析2、开发用户认证接口3、用户认证前端一、对象存储OSS 用户认证需要上传证件…

django项目实战二(django+bootstrap实现增删改查)进阶查询

目录 一、用例管理模块实现 1、创建表和数据 2、创建用例列表 1&#xff09;注册url&#xff08;用例列表&#xff09; 2)修改views.py新增case_list方法 3&#xff09;layout.html导航条新增一个用例管理 4&#xff09;新增case_list.html页面 3、新增用例页面开发 1&…

2023年TS4 入门笔记【慕课网imooc】【Vue3+React18 + TS4考勤系统】

目录 安装ts 基础 类型声明和变量声明 类型注解和类型判断 类型分类与联合类型与交叉类型​编辑 never类型与any类型与unknown类型 类型断言与非空断言 数组类型和元祖类型 对象类型与索引签名 函数类型与void类型 函数重载与可调用注解 枚举类型与const枚举 进阶…

机械革命黑苹果改造计划第四番-外接显示器、win时间不正确问题解决

问题 1.无法外接显示器 最大的问题就是目前无法外接显示器&#xff0c;因为机械革命大多数型号笔记本电脑的HDMI、DP接口都是直接物理接在独显上的&#xff0c;内屏用核显外接显示器接独显&#xff0c;英伟达独显也是黑苹果无法驱动的&#xff0c;而且发现机械革命tpyec接口还…

k8s的基础概念

目录 一、k8s概念 1、k8s是什么 2、为什么要用k8s 3、k8s的特性 二、kubernetes集群架构与组件 1、Master组件 1.1、Kube-apiserver 1.2、Kube-controller-manager 1.3、Kube-scheduler 2、配置储存中心 3、Node组件 3.1、Kubelet 3.2、Kube-Proxy 3.3、docker 或…

SAP S/4 HANA 现金流量表

S4 HANA中的现金流量表 引言&#xff1a;在传统SAP ECC中我们实现现金流量表的方式通常是定义一系列和现金流变动相关的原因代码&#xff08;Reason Code&#xff09;&#xff0c;然后在过账凭证里指定对应的Code&#xff0c;最后通过ABAP代码抓取这些数据产生现金流量表。此方…

力扣(LeetCode)417. 太平洋大西洋水流问题(2023.02.19)

有一个 m n 的矩形岛屿&#xff0c;与 太平洋 和 大西洋 相邻。 “太平洋” 处于大陆的左边界和上边界&#xff0c;而 “大西洋” 处于大陆的右边界和下边界。 这个岛被分割成一个由若干方形单元格组成的网格。给定一个 m x n 的整数矩阵 heights &#xff0c; heights[r][c]…

【pm2】pm2的安装与基本命令:

文章目录一、安装&#xff1a;二、基本命令&#xff1a;【1】启动命令&#xff1a;pm2 start app.js【2】命令行参数&#xff1a;pm2 start app.js --watch -i max【3】 查看有哪些进程&#xff1a;pm2 list【4】停止命令&#xff1a; pm2 stop app_name | app_id &#xff08;…

el-table 复杂表头行内增删改代码示例

效果如图 <template><div class"app-container"><el-card class"box-card item"><div slot"header" class"clearfix" click"showCondition !showCondition"><span><i class"el-ic…

外籍在读博士|赴新西兰奥克兰大学双院士导师麾下联合培养

N同学来自阿拉伯国家&#xff0c;但本硕博都是在我国某省属高校就读&#xff0c;现为材料学专业一年级博士生。联合培养首选澳洲国家&#xff0c;包括澳大利亚和新西兰&#xff0c;其次是美国&#xff0c;希望在2023年初出国&#xff0c;以完成整个学年的学习计划。在我们的帮助…

Android稳定性系列-01-使用 Address Sanitizer检测原生代码中的内存错误

前言想必大家曾经被各种Native Crash折磨过&#xff0c;本地测试没啥问题&#xff0c;一到线上或者自动化测试就出现各种SIGSEGV、SIGABRT、SIGILL、SIGBUS、SIGFPE异常&#xff0c;而且堆栈还是崩溃到libc.so这种&#xff0c;看起来跟我们的代码没啥关系&#xff0c;关键还不好…