【springcloud微服务】Spring Cloud Alibaba 整合dubbo与openfeign

news2024/11/29 22:50:41

一、前言

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/589801.html

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

相关文章

LabVIEWCompactRIO 开发指南第六章43

LabVIEWCompactRIO 开发指南第六章43 复用 模块中较昂贵的组件之一是ADC。通过使用多路复用器&#xff08;也称为多路复用器&#xff09;通过单个ADC路由多个通道&#xff0c;多路复用模块以比同步模块更低的每通道价格提供更高的通道数。 在学习如何对这些模块进行编程之前…

前端学习Flutter笔记(第一章:安装软件,配置环境变量等)

学习背景 人都是有惰性的&#xff0c;如果没有外界压力&#xff0c;基本不会取主动学习&#xff0c;有那个学习的时间宁愿多刷点小视频。。。。 公司有项目使用Flutter写的&#xff0c;想让我接手&#xff0c;可是咱不会啊&#xff0c;没接触过。就浅浅的在b站着了几个视频。 第…

什么是腾讯云轻量应用服务器?轻量与云服务器对比区别有哪些?

什么是腾讯云轻量应用服务器&#xff1f;轻量应用服务器是腾讯云推出的开箱即用轻量级云服务器&#xff0c;适合个人开发者或中小企业使用&#xff0c;腾讯云轻量服务器和云服务器有什么区别&#xff1f;为什么轻量应用服务器成本更低&#xff1f;是因为轻量服务器CPU内存性能比…

Transformer-《Attention Is All You Need》

目录 0.Transformer介绍 1.self-attention 和Multi-heads self-attention 1.1 self-attention&#xff08;自注意力机制&#xff09; 1.2 Multi-heads self-attention&#xff08;多头自注意力机制&#xff09; 2.网络结构 2.1 encoder&#xff08;编码器&#xff09; 2…

【尔嵘】感恩四周年,感谢支持

前言 注意&#xff1a;为感谢各位铁粉支持&#xff0c;【尔嵘】将随机一个号码赠送一本vue.js书籍&#xff0c;欢迎评论区留言&#xff01; 在当前互联网领域中&#xff0c;CSDN是一个非常知名的技术社区&#xff0c;在这里你可以接触到很多高质量的技术文章和技术交流。对于技…

九年测试老鸟,写给1~5年的测试工程师的几点建议,满满硬货指导

从15年毕业到现在也从业八年了&#xff0c;普通本科毕业&#xff0c;现在一家互联网公司担任测试部门总监&#xff0c;摸爬打滚&#xff0c;坑坑洼洼也经历了不少。思绪很久决定还是写下这篇&#xff0c;希望对后进的小伙子少走一点弯路。 很多人把职场想得太美好&#xff0c;其…

七人拼团系统开发模式详解

七人拼团是最近兴起的一个模式&#xff0c;它通过更人性化的奖励机制&#xff0c;将产品利润最大化让利给参与拼团的用户&#xff0c;达到促进用户主动积极裂变和团队平台引流提升销量的效果&#xff0c;下面就来详细说一下这个模式。 七人拼团最大的特点&#xff0c;就是结合了…

JVM之栈和堆运行时内存深度剖析

运行时内存篇 程序计数器 也是线程私有的,不共享,因为cpu时间片轮换的缘故,所以需要记录上次未执行完的线程执行到那条字节码指令了,所以每个线程需要记录当前执行的命令的内存指针,以方便线程再次得到执行的时候按照正确的顺序执行 JVM之栈(虚拟机栈) 基础知识 会gc吗 不…

pinpoint安装部署(相关博客合集)

pinpoint安装部署 说明一、PinPoint介绍及工作原理1.1 确定部署的组件及服务 二、相关组件版本兼容情况2.1 确定版本 三、部署3.1 HBASE3.2 agent 说明 本博客写在搭建PinPoint之前&#xff0c;主要是用来记录查阅的相关博客资料&#xff0c;等到动手搭建完再更新实际部署操作…

医学可视化应用简介

VolView VolView是一款为临床专业人员开发的开源放射学查看器。使用VolView&#xff0c;可以通过交互式电影体积渲染对数据有更深入的视觉理解&#xff0c;并轻松地以3D形式可视化DICOM数据。由于VolView在浏览器中运行&#xff0c;不需要安装软件&#xff0c;数据也可以安全地…

SOLIDWORKS技巧培训-绘制零件滚花的两种方法

最近常有朋友咨询SolidWorks零件如何做滚花的效果&#xff0c;下面给大家整理了绘制零件滚花的一个培训教程&#xff1a; 作为机械设计师&#xff0c;滚花应该都不陌生&#xff0c;真要说起来&#xff0c;滚花绘制其实也不算难&#xff0c;跟着我们一步一步来&#xff0c;应该…

DATAX数据同步工具

1&#xff1a;DATAX概览 ​ DataX 是一个异构数据源离线同步工具&#xff0c;致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。 1.1&#xff1a;DataX3.0框架设计 DataX本身作为离线数据同步框架&am…

NR RLC(四) AM mode

欢迎关注同名微信公众号“modem协议笔记”。 这篇是RLC AM mode的相关内容&#xff0c;RLC的ARQ是一种重传机制&#xff0c;其实NR三个不同的协议层MAC(HARQ)、 RLC(ARQ)和PDCP都有重传功能。为什么三层协议都需要具备重传功能&#xff1f;早期也有思考过这个问题&#xff0c;…

Sui与KuCoin Labs联合推出夏季黑客松,奖池高达28.5万美金!

Sui与KuCoin Labs联合推出的夏季黑客松于2023年5月29日正式开启&#xff0c;本次黑客松将为参赛者提供与Sui基金会团队、KuCoin Labs和其他黑客松合作伙伴及支持者进行技术交流和项目演示的机会。比赛涵盖四个主要赛道&#xff0c;总奖池高达28.5万美金&#xff0c;最终比赛结果…

【目标检测】yolov5模型详解

文章目录 一、Yolov5网络结构1.1 Input1.2 Backbone1.2.1 Conv模块1.2.2 C3模块1.2.3 SPPF模块 1.3 Neck1.4 Head1.4.1 head1.4.2 目标框回归1.4.3 目标的建立1.4.4 NMS&#xff08;Non-Maximum Suppression&#xff09; 二、损失函数2.1 分类损失2.2 置信度损失2.3 定位损失 L…

在Linux系统实现服务器端和客户端的套接字通信

目录 一.创建一个socket文件夹用来存放编写的服务器端和客户端程序 二.编写服务器端代码 三.编写客户端代码 四.编译c语言程序 五.断开连接 六.可能涉及到的一些没接触过的知识点 一.创建一个socket文件夹用来存放编写的服务器端和客户端程序 &#xff08;我系统里的文件…

Revit楼板问题:楼板连接处以及楼板开洞,一键开洞

在我们做楼梯时&#xff0c;楼梯与楼板处的连接处理不是那么符合实际&#xff0c;会出现一些问题&#xff0c;如下图&#xff0c;这样的连接会导致楼梯配筋时钢筋外露。 我们来学习如何调节楼板与楼板连接处的高度&#xff0c;选中楼梯&#xff0c;点击“编辑楼梯”在所需要更改…

STM32堆栈方面知识点

最近弄json&#xff0c;发现经常的堆溢出&#xff0c;然后找问题。因为对STM32堆栈问题没有深刻认识&#xff0c;就花时间好好研究下了堆栈并且做了验证 1.栈地址区间确定 首先找到启动文件&#xff0c;我的启动文件在startup_stm32f40xx.s&#xff0c;一般的启动文件也都在s…

Linux之命令搜索

目录 Linux之命令搜索 Whereis命令 定义 基本信息 举例 which命令 定义 与whereis命令的区别 基本信息 举例 locate 命令 定义 优点 缺点 基本信息 案例 Linux之命令搜索 Whereis命令 定义 whereis --- 搜索系统命令的命令&#xff08;像绕口令一样&#xff09…

Revit中如何为曲面墙体开洞口,一键开洞?

一、Revit中如何为曲面墙体开洞口 直线墙体开洞可以直接通过编辑轮廓来绘制洞口形状即可&#xff0c;或者可以通过选中墙体选择“墙-洞口”命令来开洞口。 但是曲面墙体开洞并没有那么简单&#xff0c;曲面墙体不能够编辑轮廓&#xff0c;并且选中曲面墙体“墙-洞口”命令只能够…