Spring Cloud Alibaba 同时兼容dubbo与openfeign

news2024/11/25 4:50:26

一、前言

dubbo与springcloud都可以单独作为微服务治理框架在生产中进行使用,但使用过springcloud的同学大概了解到,springcloud生态的相关组件这些年已经逐步停更,这就导致在服务架构演进过程中的迭代断层,以至于一些新的技术组件引入困难重重,于是在国内的市场上就有了升级版的springcloud-alibaba。

二、springcloud-alibba与dubbo对比

2.1 springcloud-alibaba 简述

Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案。此项目包含开发分布式应用微服务的必需组件,方便开发者通过 Spring Cloud 编程模型轻松使用这些组件来开发分布式应用服务。

2.1.1 主要技术组件介绍

springcloud-alibaba提供了丰富的服务治理技术组件,列举如下:

  • Sentinel:流控治理组件,以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性;
  • Nacos:一个更易于构建云原生应用的集动态服务发现、分布式配置管理和服务管理平台;
  • RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务;
  • Dubbo:Apache Dubbo™ 是一款高性能 Java RPC 框架,可以单独作为服务治理框架;
  • Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案;
  • Alibaba Cloud ACM(收费等同于Nacos):一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品;
  • Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据;
  • Alibaba Cloud SchedulerX: (收费) 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务;
  • Alibaba Cloud SMS: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道;

利用上述这些组件的组合,可以较好的完成生产级项目的微服务改造,从技术演进来看,这一套技术组件也在逐步适配云原生的脚步,可以不用担心未来集成云原生过程中遇到问题得不到解决的麻烦。

2.1.2 springcloud-alibaba使用场景

springcloud架构升级改造

由于springcloud生态下部分组件很长时间未做更新,针对那些之前使用原生的springcloud但是又需要对架构进行更深层次的优化、调整、扩展等治理需求的场景。

更完备的流控治理

springcloud-alibaba中的sentinel,在流控治理方面更加出色,尽管springcloud中也有hystrix用于服务的降级、流控等功能,但是功能仍然比较单一。

服务与配置的集中式管理

springcloud-alibaba中nacos集服务与配置管理为一体,而且提供更友好更便捷的可视化界面方便开发运维使用,可以减少部署和运维成本,而原生的springcloud则需要同时使用eureka以及引入其他的配置管理组件共同使用。

容器化部署与云原生支持

背后有强大的技术团队背书,以及阿里云对云原生技术的支撑与融合,Spring Cloud Alibaba 支持 Kubernetes、Docker 等容器化技术,可以方便地部署。

跨应用接口调用

springcloud实现微服务之间相互调用主要是通过http接口实现的,对于不同应用跨机器,甚至跨网络部署的场景可以考虑使用。

2.2 dubbo 简述

Dubbo是阿里开源的分布式服务治理框架,其使用简单,高效便捷的使用方式得到跟多架构师的青睐,底层以RPC方式调用远程服务。

dubbo提供了三大核心能力:

  • 面向接口的远程方法调用;
  • 智能容错和负载均衡;
  • 以及服务自动注册和发现;

2.2.1 dubbo业务模型

下面这张图是dubbo的模型架构图,不难看出,架构中主要包括4部分:

  • Registry,服务注册中心;
  • Provider,服务提供方,对外或其他应用提供服务接口;
  • Consumer,服务消费方,调用Provider提供的服务,像本地一样调用;
  • Monitor,服务监控,一般很少使用;

2.2.2 dubbo使用场景

尽管dubbo也可以单独拿出来作为微服务治理的框架,而且在很多公司中也是广泛实用,与springcloud-alibaba相比,大部分场景下都是可以互相替代的,关于dubbo的使用场景,这里总结下面几点作为参考;

微服务架构改造

微服务架构下服务的拆分很细,服务之间需要相互调用,使用Dubbo可以方便地实现微服务之间的通讯,对于服务消费方来说,只需引入提供方的SDK,像本地调用一样方便;

分布式系统

在分布式系统中,各微服务模块需要互相合作处理任务,这时可以考虑使用Dubbo作为服务调用中间件

内部系统架构

平台级内部各应用之间在进行服务的相互调用时,使用dubbo比springcloud在传输效率更高效

高并发、大流量场景

dubbo底层使用的是netty,相比http来说,一定程度上传输效率更好,在高并发下,dubbo的优势更明显

更关注接口级的API治理

dubbo提供了完备的服务治理技术,基于服务治理的思想提供了一整套服从务发现、负载均衡、容错机制、线程调优、通讯协议等解决方案,对API层面的治理更为友好和精细

三、服务改造的难题

3.1 技术选型难题

对于一个稍成规模的公司级产品来说,技术架构当然不是一成不变的,但有一点相信很多伙伴还是能达成共识的,即对大多数中小型公司的产品来说,其技术架构在相当长的一段时间内很难做较大的调整,而技术架构在一开始的选型之后基本上算是定型了,为什么这么说呢?

3.1.1 技术负责人的技术风格

可以说,很多团队的技术负责人的技术栈广度和深度在很大程度上面决定了一个产品的架构基调,有些负责人对dubbo技术比较深入,可能一开始就选择了使用dubbo作为服务治理框架,而如果对springcloud熟悉的话,可能就会偏向于springcloud;

3.1.2 业务增长快速难以定性

这几年,市场上很流行DDD的概念,事实上真正推动DDD落地还是有相当的代价的,这个需要公司的业务模型相对稳定、清晰、并且具备一定的可控性,假如一个公司的业务处于快速的扩张中,那将充满着较多的不确定性,不确定性带来的直接问题就是,技术架构在选型上需要进行合理的权衡,既不能太复杂,但也需要留有一定的扩展性,为后续架构的扩展留有余地,由于业务上的不确定性很难说采用那种微服务框架是服务治理的最好模式;

3.1.3 微服务框架的融合难题

不少同学肯定遇到这样的场景,比如说你的springboot版本是1.5.X,现在需要升级到2.X版本,看起来只是一个jar包版本的升级问题,但是有过升级经验的同学来说,这个升级过程堪比西天取经,苦难重重不说,一大堆的坑要填,最后还要深入到代码层面层层调整...

涉及到框架层面的调整也是司空见惯的事,举例来说,你的微服务治理框架使用的是springcloud,但是发现对于配置中心的管理使用git实在很不方便,而且配置托管在外网上总觉得不踏实,需要收回来,或者说,你需要对整个平台的各个微服务进行统一的可视化流控治理,如果你觉得springcloud中的hystrix不好用,可能会想到引入其他的第三方流控治理组件...

上面的这个情形就是,头疼医头,脚痛医脚,最后整个产品引入的第三方技术组件越来越多,维护的成本越来越高,部署、运维要投入的人力也越来越多,更要命的事情是,一旦出了问题,解决问题的效率很低。究其原因,原生的springcloud框架自身在微服务治理体系下,在应对如今越来越复杂的服务治理需求上,开始显得力不从心,于是很多人开始考虑springcloud-alibaba进行整合并实现架构上的调整。

事实上,尽管springcloud-alibaba也是完美支持springcloud并且做了不少的升级,但是从架构调整来说,这也是一项改造量相当大的工作,主要难题聚集在下面几点:

顶级pom依赖不兼容

springcloud与springcloud-alibaba的根pom适配版本是不相同的,毫不夸张的说,springcloud-alibaba几乎不可能与springboot 1.5.X系列的版本在一起工作了;

内部组件需要调整和兼容

springcloud的注册中心是eureka,而springcloud-alibaba的配置管理主推nacos,如何将eureka调整为使用nacos?还是直接在springcloud-alibaba中继续使用nacos呢?

部署模式上的调整

springcloud-alibaba有阿里技术团队背书,其部署模式在适配容器化以及云原生上具有天然的优势,而springcloud在这一点来说已经失去了竞争力,但同时,这也给技术团队从开发到运维提出了更高的要求;

团队人员的学习成本

相对而言,springloud-alibaba涉及到的技术栈更为全面,并且今后考虑与云原生融合的话这个学习成本甚至更高,这就需要开发人员掌握更多的新的技能,这项成本不能不考虑。

3.2 dubbo与springcloud的融合难题

随着dubbo在微服务治理中的优势越来越明显,springcloud-alibaba这一套治理体系为了能够一通吃掉也是煞费苦心,举个实际的场景来说,假如你现在所在团队使用的是springcloud-alibaba这一套框架,那么服务之间的RPC调用自然少不了ribbon或者openfeign;

以openfeign为例进行说明,对于服务消费方来说,使用起来很方便,也很顺手,调用远程服务的时候像是调用本地服务一样简单,但是,从单个API服务的治理和管控来说,不管是openfeign,还是ribbon,都不是很友好,而且就算是进行治理,还需要借助外部的手段,比如agent,或者编码的方式,或者其他的外部组件进行服务监测,比较要命的是,如果都是内部的服务,走openfeign的调用,在高并发场景下,这个性能问题多少会暴露出来;

于是架构师或技术负责人想到如果能使用dubbo就好了,毕竟人家dubbo在API级别的服务治理上还是很出色,并且提供了一整套治理方案的。但是直接生硬的把openfeign干掉更换dubbo也是不现实的,如果微服务模块多的话,那就不是单单改造一个两个应用的事情了。

于是,进一步思考,能否采用折中的方案,在现有的基础上引入dubbo,即同时支持openfeign与dubbo的调用呢?这个考虑似乎可行,而且也是一种相对合理的解决方案,事实上,很多产品在做架构调整上也是依照这个思路,为了干掉旧的,引入新的技术,然后让新旧并存一段时间之后再逐步废弃旧的技术。

以上面的场景和解决思路为背景,下面以实际操作案例演示使用springcloud-alibaba 整合dubbo与openfeign的完成过程。

四、springcloud-alibaba整合openfeign

4.1 前置准备

为了方便后文的测试,提前创建一个数据库并创建一张测试使用的数据表,数据库名为:dbuser01,建表sql如下:

CREATE TABLE `user` (
  `id` varchar(32) NOT NULL,
  `user_name` varchar(32) NOT NULL,
  `pass_word` varchar(32) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


INSERT INTO `dbuser01`.`user`(`id`, `user_name`, `pass_word`) VALUES ('001', 'jerry', '123456');
INSERT INTO `dbuser01`.`user`(`id`, `user_name`, `pass_word`) VALUES ('002', 'mike', '123456');
INSERT INTO `dbuser01`.`user`(`id`, `user_name`, `pass_word`) VALUES ('003', 'john', '123456');

4.2 操作步骤

4.2.1 工程目录结构

完整的工程目录结构如下

4.2.2 父模块导入如下依赖

根pom中定义基础的全局版本号依赖,这里主要包括:springcloud,springcloud-alibaba等版本,其他的可以在具体模块中增量补充即可,另外需要注意springcloud 与springcloud-alibaba以及springboot的版本兼容性问题,这个可以参考相关的资料,网上有很多。

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.9.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
        <mysql.version>5.1.47</mysql.version>
        <mybatis.version>2.1.1</mybatis.version>

        <dubbo.version>2.7.18</dubbo.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>

            <!-- mysql驱动 -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>

            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.6.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

        </dependencies>
    </dependencyManagement>

    <dependencies>

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

4.2.3 服务提供方核心依赖

主要包括:mysql连接,mybatis,nacos服务注册中心,以及openfeign的依赖,dubbo的依赖可以在后面添加;

    <dependencies>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>com.congge</groupId>
            <artifactId>biz-common</artifactId>
            <version>1.0</version>
        </dependency>

        <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配置管理依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <!-- Dubbo Spring Cloud Starter -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-dubbo</artifactId>
        </dependency>

    </dependencies>

4.2.3 公共模块定义实体类和服务接口

在公共模块中定义一个实体类,与数据库user表映射,注意这里一定要实现序列化,避免后面调用dubbo接口时出现序列化错误;

@Data
public class User implements Serializable {

    private static final long serialVersionUID = -2896873555774275129L;
    private String id;
    private String userName;
    private String passWord;

}

定义服务接口 UserDubboApiService

public interface UserDubboApiService {
    User getById(String id);
}

最后,将common模块通过mvn的install命令安装到本地仓库,然后引用到其他两个模块中

4.2.4 服务提供方核心代码

核心配置文件


server:
  port: 8081

spring:
  application:
    name: biz-provider-service

  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

  datasource:
    url: jdbc:mysql://IP:3306/dbuser01?useUnicode=true&characterEncoding=utf-8
    username: 用户名
    password: 密码
    driver-class-name: com.mysql.jdbc.Driver


#mybatis相关配置
mybatis:
  type-aliases-package: com.congge.entity
  configuration:
    map-underscore-to-camel-case: true
  mapper-locations: classpath:mybatis/*.xml

添加一个服务接口用于测试

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    //http://localhost:8081/user/getById?id=001
    @GetMapping("/getById")
    public Object getByUserId(@RequestParam("id") String id){
        /*User user = new User();
        user.setId("001");
        user.setUserName("jerry");
        user.setPassWord("123456");
        return user;*/
        return userService.getById(id);
    }

}

服务实现

import com.congge.entity.User;
import com.congge.mapper.UserMapper;
import com.congge.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public User getById(String id) {
        return userMapper.getById(id);
    }

}

服务启动类

@SpringBootApplication
@EnableFeignClients
@MapperScan("com.congge.mapper")
public class BizProviderApp {

    public static void main(String[] args) {
        SpringApplication.run(BizProviderApp.class,args);
    }

}

4.2.5 服务提供方接口测试

这里使用了nacos作为服务注册中心,因此在启动服务之前,需要启动nacos

启动提供方的服务,然后浏览器调用一下测试接口,看到下面的效果说明整合完成;

4.2.6 服务消费方核心代码

工程目录结构,依赖与生产方的相同,就不再赘述了

添加一个Feign的接口类

import com.congge.entity.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.Map;

@FeignClient(name = "biz-provider-service",path = "/user")
public interface UserFeignService {

    @GetMapping("/getById")
    public User get(@RequestParam("id") String id);

}

添加一个测试接口,这里为了方便省略了服务实现类,实际开发中建议添加实现类

@RestController
public class BizMockController {

    @Autowired
    private UserFeignService userFeignService;

    //localhost:8082/getFromRemote
    @GetMapping("/getFromRemote")
    public Object getFromRemote(){
        return userFeignService.get("001");
    }


}

核心配置文件,主要是配置一个工程的服务名注册到nacos;


server:
  port: 8082

spring:
  application:
    name: biz-consumer-service

  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #服务注册中心地址

服务启动类

@SpringBootApplication
@EnableFeignClients
public class BizConsumerApp {

    public static void main(String[] args) {
        SpringApplication.run(BizConsumerApp.class,args);
    }
}

4.2.7 服务消费方接口测试

以上步骤做完后,启动消费方服务,通过上面提供的测试接口调用一下,看到下面的效果,说明消费方通过openfeign调用远程的服务完成;

五、springcloud-alibaba整合openfeign并兼容dubbo

回到第三章中最后的原始诉求,当工程需要适配架构调整,引入dubbo框架时该怎么做呢?改造的效果是,对于服务消费方来说,原来已经在使用openfeign的继续使用,同时可以更换openfeign的调用为dubbo调用,接下来做对上述的两个模块代码做一些调整即可;

5.1 服务提供方改造

5.1.1 添加dubbo依赖

注意这里直接引入的是springcloud整合的dubbo而没有单独引dubbo依赖,也可以自己单独引,但是需要注意版本匹配的问题(慎重慎重)

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

通过点击进去可以发现这里使用的是2.7.8的dubbo版本,而在这个版本中,dubbo在配置时可以不用依赖zk了,所以我并没有引zk或curator相关依赖;

5.1.2 增加dubbo相关配置

dubbo的配置这里只添加了基础的配置信息,相信使用过的同学应该不陌生,主要是一个dubbo协议,端口,外加dubbo扫描的业务实现类包路径;

dubbo:
  protocol:
    name: dubbo
    port: 20881
  scan:
    base-packages: com.congge.service.impl.dubbo

5.1.3 代码改造

引入dubbo后,为了方便开发的包目录清晰,以及减少后续的维护成本,将工程的目录结构做如下调整:

关于该目录结构,做如下补充说明,也是一种生产上的实践经验:

  • dubbo的实现类建议与工程自身的业务实现类分开;
  • 本工程的业务实现类主要编写自身的业务给当前工程使用;
  •  dubbo的业务实现类单独提供服务实现,给其他调用方使用;
  • 为了减少编码的冗余和维护成本,针对两者相同的或者重用度很高的逻辑,建议再单独拿出一个包目录,在该目录下编写通用的业务逻辑被两个实现类引用;

添加dubbo实现类,这里的UserDubboApiService即为公共模块中定义的服务接口;

import com.congge.entity.User;
import com.congge.service.UserDubboApiService;
import com.congge.service.UserService;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;

@DubboService
public class UserDubboApiServiceImpl implements UserDubboApiService {

    @Autowired
    private UserService userService;

    @Override
    public User getById(String id) {
        User dbUser = userService.getById(id);
        return dbUser;
    }

}

服务提供方的代码到这里就改造完成了,接下里看消费方的改造

5.2 服务消费方改造

大体步骤和生产方差不多,引入dubbo依赖和上面相同

5.2.1 配置文件改造

补充dubbo的配置,添加下面这段即可

dubbo:
  protocol:
    name: dubbo
    port: 20882

5.2.2 添加测试接口

添加一个测试接口,用于通过dubbo接口调用

@RestController
public class BizMockController {

    @Autowired
    private UserFeignService userFeignService;

    //localhost:8082/getFromRemote
    @GetMapping("/getFromRemote")
    public Object getFromRemote(){
        return userFeignService.get("001");
    }

    @DubboReference(retries = 0, timeout = 10000)
    private UserDubboApiService userDubboApiService;

    //localhost:8082/getFromDubbo
    @GetMapping("/getFromDubbo")
    public Object getFromDubbo(){
        return userDubboApiService.getById("002");
    }

}

5.2.3 接口测试

分别启动生产方和消费方的服务,调用上述的新增的接口,看到下面的效果说明通过dubbo也能成功调用远程服务;

小结,通过上面的改造就完成了从单独使用openfeign到同时兼容dubbo的效果,当然,有两点还需要再次强调一下:

1)版本兼容性问题,这也是在实际引入新的外部组件时与当前工程的springboot版本兼容性最容易踩坑的地方;

2)引入dubbo之后,如何更优雅的管理好本工程自身的业务实现与dubbo的业务实现;

六、写在文末

本文从一个生产实践中可能遇到的技术架构上的调整问题,通过实践操作,详细说明了如何在openfeign中引入dubbo,使得当前的服务提供方同时兼容这两种服务调用的模式,事实上,实际项目中,影响的外部因素可能源于比这个复杂,不过可以作为一个参考提供一个解决的思路,最后感谢各位的观看。需要源码的同学可前往下载:源码地址

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

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

相关文章

聚合/组合

谨慎使用继承的方式来进行扩展&#xff0c;优先使用聚合/组合的方式来实现。 Father类里有两个方法A和方法B&#xff0c;并且A调用了B。子类Son重写了方法B&#xff0c;这时候如果子类调用继承来的方法A&#xff0c;那么方法A调用的就不再是Father.B()&#xff0c;而是子类中的…

使用kali里的dnschef进行DNS欺骗

1. 前言 DNSChef是针对渗透测试人员和恶意软件分析师的高度可配置的DNS代理。它能够精细配置哪些DNS回复以修改或简单地代理真实响应。为了利用该工具&#xff0c;您必须手动配置DNS服务器以指向DNSChef。 2. 执行参数 选项参数&#xff1a; -h,--help显示帮助信息并退出--f…

C语言:计算 1! + 2! + 3! + ... + n!

题目&#xff1a; 从键盘输入一个值n&#xff0c;计算 1的阶乘 至 n的阶乘 的和&#xff0c; 如&#xff1a;输入10&#xff0c;计算 1的阶乘 至 n的阶乘 的和 --> 计算&#xff1a;1! 2! 3! ... 10! 思路一&#xff1a; 效率比较低&#xff0c;会重复计算之前计算过的…

Stable Diffusion 从听说到超神日记

1.安装模型&#xff08;B站搜秋叶&#xff09; 2.下载模型&#xff0c;安装好的界面有模型下载 有了上面模型已经可以根据模型风格去生成一些照片了 3.使用Additional Networks/lora模型 模型大多都是继承了很多网友自行训练的图库模型&#xff0c;各类风格都有&#xff01; …

分享一个卡通人物

这几天较忙&#xff0c;像它一样&#xff1a; 代码在这里&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>卡通打字</title><script src"https://s3-us-west-2.amazonaws…

《MySQL(五):基础篇- 多表查询》

文章目录 5. 多表查询5.1 多表关系5.1.1 一对多5.1.2 多对多5.1.3 一对一 5.2 多表查询概述5.2.1 数据准备5.2.2 概述5.2.3 分类 5.3 内连接5.4 外连接5.5 自连接5.5.1 自连接查询5.5.2 联合查询5.6.2 标量子查询5.6.3 列子查询5.6.5 表子查询 5.7 多表查询案例 5. 多表查询 我…

【Sql】根据字段分组排序,取其第一条数据

【Sql】根据字段分组排序&#xff0c;取组内第一条数据 【一】问题描述【二】解决方案&#xff08;oracle和mysql都可用&#xff09;【三】总结 【一】问题描述 &#xff08;1&#xff09;问题描述 有时候我们需要对数据进行去重处理&#xff0c;例如查询结果里的文件名有重复…

常用模拟低通滤波器的设计——契比雪夫I型滤波器

目录 常用模拟低通滤波器的设计——契比雪夫I型滤波器 1、cheb1ap 函数 2、cheb1ord 函数 3、cheby1函数 4、实例演示 常用模拟低通滤波器的设计——契比雪夫I型滤波器 巴特沃斯滤波器的频率特性曲线在通带和阻带内&#xff0c;幅度特性是单调下降的&#xff0c;如果阶次一…

RISC-V体系结构的U-Boot引导过程

RISC-V体系结构的U-Boot引导过程 flyfish BootLoader Boot是Bootstrap&#xff08;鞋带&#xff09;的缩写&#xff0c;它来自于一句谚语&#xff1a;“Pull oneself up by one’s own bootstraps”&#xff0c;直译的意思是“拽着鞋带把自己拉起来” 干这件事&#xff0c;得…

文心一言 VS 讯飞星火 VS chatgpt (33)-- 算法导论5.2 5题

五、设A[1…n]是由n个不同数构成的数列。如果i<j且A[i]>A[j]&#xff0c;则称(i&#xff0c;j)对为A的一个逆序对(inversion)。(参看思考题2-4 中更多关于逆序对的例子。)假设A的元素构成(1&#xff0c;2&#xff0c;… &#xff0c;n)上的一个均匀随机排列。请用指示器随…

Win11配置Anaconda-Cuda-Pytorch-Tenserflow环境

之前搞了一个月左右时间用WSL2跑模型&#xff0c;后来发现还是不太习惯&#xff08;其实用不明白&#xff09;&#xff0c;就转成Windows了。这次也是记录一下自己配环境的过程&#xff0c;以免下次还需要 安装Anaconda 下载方式 Anaconda官网清华镜像下载 tip&#xff1a;…

OpenHarmony源码解析(11): hiview维测平台

作者: 鸿湖万联(武汉) 许文龙 1、概述 Hiview是一个跨平台的终端设备维测服务集,由插件管理平台和基于平台上运行的服务插件来构成整套系统。Hiview维测服务是由HiSysEvent事件驱动的,其核心为分布在系统各处的HiSysEvent桩点,格式化的事件会通过HiSysEvent打点API上报至H…

Tomcat【尚硅谷】

一、Tomcat基础 1、常见的web服务器 概念 服务器&#xff1a;安装了服务器软件的计算机服务器软件&#xff1a;接收用户的请求&#xff0c;处理请求&#xff0c;做出响应web服务器软件&#xff1a;在web服务器软件中&#xff0c;可以部署web项目&#xff0c;让浏览器来访问这…

【模块系列】DHT11时序理论

前言 基于stm32f103C6T6核心板STM32CubeMX的DHT11的使用。其实吧&#xff0c;要不是网上关于stm32调用DHT11的代码大多数用不了或者乱七八糟的&#xff0c;我也不想推时序的&#xff0c;嘎嘎麻烦。写着写着就发现&#xff0c;本章的篇幅有点长了&#xff0c;所以本文就先介绍DH…

Fiddler抓包返回的Response中总是出现“Response body is encoded. Click to decode. “的解决办法

在进行网页开发和接口调试时&#xff0c;我们经常会用到Fiddler这个工具。 但是&#xff0c;有时候我们会遇到一个非常头疼的问题&#xff0c;就是在抓取网页返回的Response时总是出现“Response body is encoded. Click to decode.”的提示。 这种情况下我们可能无法正常查看…

【Web服务应用】Nginx七层反向代理与四层反向代理

Nginx七层反向代理与四层反向代理 一、代理1.1什么是代理1.2正向代理1.3反向代理1.4反向代理的适用场景1.5正向代理与反向代理的区别 二、反向代理2.1负载均衡2.2动静分离 三、Nginx实战3.1七层反向代理&#xff0c;负载均衡&#xff0c;动静分离3.2四层反向代理 一、代理 1.1…

测试复习(自用)

测试复习 通识/基础/概念 什么是软件测试 验证软件特性是否满足用户的需求 专业名词 需求 满足用户期望或正式文档&#xff08;合同、标准、规范&#xff09;所具备的条件和权能&#xff0c;包含用户需求和软件需求 用户需求软件需求 是测试人员开展软件测试工作的依据 如…

【Mysql】基础入门篇

文章目录 什么是数据库见见数据库服务器、数据库、表之间的关系数据逻辑存储MySQL架构SQL分类存储引擎 什么是数据库 存储数据用文件就可以了&#xff0c;为什么还需要数据库&#xff0c;文件保存数据有以下几个缺点&#xff1a; 文件的安全性问题 文件不利于数据查询和管理 文…

五年后,你是什么档次

每晚一到两篇的阅读 1.认清现实&#xff0c;她就是喜欢钱 2.不要再找理由&#xff0c;自卑才是你最大的动力 3.提高自己的任性指数 4.尽量把钱花在有营养的地方 5.不要成为一条被溺死的鱼 6.总有一天&#xff0c;卫生纸比钞票值钱 7.穷忙的人&#xff0c;不要开Toyota 8.目标就…

easypoi模板导出文件,支持Liunx系统(自用)

springboot使用easypoi通过使用模板导出文件 第一步:导入poi以及easypoi的maven坐标 首先&#xff0c;easypoi是依赖于Apache的poi实现的&#xff0c;因此需要先引入poi <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifac…