从0到1的Springcloud Alibaba项目,一篇入门!!!

1、新建项目

我们用maven管理项目

第一步:选择maven

第二步:项目命名,项目路径

第三步:进入项目,把src文件夹删掉(不删也没事,主要是用不到这个文件夹)

2、引入项目依赖

在父项目pom文件加入下面依赖。

注:springboot项目版本与cloud版本有一定的对应关系,在官网可以看到,下面是对应的版本关系,选择合适的即可。

本项目所用依赖版本:

<?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>org.example</groupId><artifactId>project_springcloud</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target><!--springboot版本--><spring.boot.version>2.3.8.RELEASE</spring.boot.version><!--springcloud版本--><spring.cloud.version>Hoxton.SR10</spring.cloud.version><!--springcloudalibaba版本--><spring.cloud.alibaba.version>2.2.1.RELEASE</spring.cloud.alibaba.version></properties><!-- 管理依赖的版本 --><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring.boot.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring.cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
</project>

注意:

  1. 父工程dependencyManagement中管理的依赖在你们仓库中可能没有,所以要注释dependencyManagement先下载对应版本的依赖
  2. dependencyManagement只是声明依赖,并不实现引入,因此子项目需要显示声明需要用的依赖

3、Nacos服务注册和发现

3.1、Nacos下载与启动

模拟生产环境,采用Linux部署

第一步:官网下载nacos(Nacos | Nacos),下载不了的可以关注公众号【JavaCoding】回复nacos获取

第二步:进入bin文件,修改startup.sh配置文件,下载的默认启动配置需要的内存太大,改小一点

第三步:命令启动sh startup.sh -m standalone,注:这里standalone参数代表着单机模式运行,非集群模式

控制台输出这样的内容代表启动成功,我们打开start.out日志查看内容:

3.2、服务注册

第一步:新建一个服务service1

要在父级目录下创建service1项目,具体步骤与上述创建父项目类似,过程省略,创建后的项目结构如下:

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>project_springcloud</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>service1</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${spring.boot.version}</version></dependency><!--nacos服务注册--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>${spring.cloud.alibaba.version}</version><exclusions><exclusion><artifactId>nacos-client</artifactId><groupId>com.alibaba.nacos</groupId></exclusion></exclusions></dependency><!--nacos配置中心--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>${spring.cloud.alibaba.version}</version><exclusions><exclusion><artifactId>nacos-client</artifactId><groupId>com.alibaba.nacos</groupId></exclusion></exclusions></dependency><!--单独指定nacos client版本(自带的版本会在控制台一直输出日志)--><dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId><version>1.4.2</version></dependency></dependencies></project>

第二步:登录我们启动的nacos地址,新建一个命名空间

第三步:点击配置列表右侧加号,新建一个配置

第四步:yml中配置(注意这里项目中配置文件名一定要是bootstrap)

spring:application:name: service1cloud:nacos:discovery:# 你的服务器ipserver-addr: 114.115.xxx.xx:8848namespace: 900c8c5e-b442-4b61-abf4-90b640e643eaconfig:server-addr: 114.115.xxx.xx:8848namespace: 900c8c5e-b442-4b61-abf4-90b640e643eaprefix: service1group: DEFAULT_GROUPfile-extension: yaml

最后启动项目:

我们可以看到,项目端口是用的我们nacos里配置里写好的端口

点开nacos服务列表:

我们可以看到我们启动的服务已经注册进来了,这里的服务名就是我们项目里spring.application.name配置的名

最后接口测试:

注意:

我们这里的启动类并没有加@EnableDiscoveryClient注解,是因为从Spring Cloud Edgware开始,这个注解可以省略。但是maven依赖中必须要有spring-cloud-starter-alibaba-nacos-discovery服务注册的依赖。

但是值得注意的是,如果使用了Eureka作为注册中心,那么需要使用@EnableEurekaClient注解来启动Eureka客户端。因此,是否需要省略@EnableDiscoveryClient注解取决于你的具体需求和使用的服务注册中心类型。

4、Gateway网关服务

4.1、项目引入

第一步:新建Gateway项目,过程省略,项目结构如下

第二步:引入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>project_springcloud</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>gateway</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><!--gateway依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--nacos服务注册--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId><version>${spring.cloud.alibaba.version}</version><exclusions><exclusion><artifactId>nacos-client</artifactId><groupId>com.alibaba.nacos</groupId></exclusion></exclusions></dependency><!--nacos配置中心--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>${spring.cloud.alibaba.version}</version><exclusions><exclusion><artifactId>nacos-client</artifactId><groupId>com.alibaba.nacos</groupId></exclusion></exclusions></dependency><!--单独指定nacos client版本(自带的版本会在控制台一直输出日志)--><dependency><groupId>com.alibaba.nacos</groupId><artifactId>nacos-client</artifactId><version>1.4.2</version></dependency></dependencies></project>

第三步:nacos新增配置文件,与service1一样,端口我们设置为8002

第四步:配置文件

spring:application:name: gatewaycloud:nacos:discovery:server-addr: 114.115.xxx.xx:8848namespace: 900c8c5e-b442-4b61-abf4-90b640e643eaconfig:server-addr: 114.115.xxx.xx:8848namespace: 900c8c5e-b442-4b61-abf4-90b640e643eaprefix: gatewaygroup: DEFAULT_GROUPfile-extension: yaml

第五步:启动项目

在nacos里可以看到我们的Gateway服务已经注册进来了

4.2、路由配置

上面步骤我们只是把Gateway服务启动,并没有体现出Gateway的作用,我们想要看到的是通过访问不通的接口,Gateway可以帮我自动找到到相应的服务。

简单介绍Gateway配置项:

路由(Route):由ID、目标URI、断言集合和过滤器集合组成。如果聚合断言结果为真,则转发到该路由。

(1)id:路由标识,要求唯一,名称任意(默认值 uuid,一般不用,需要自定义)

(2)uri:请求最终被转发到的目标地址

(3)order: 路由优先级,数字越小,优先级越高

(4)predicates:断言数组,即判断条件,如果返回值是boolean,则转发请求到 uri 属性指定的服务中

(5)filters:过滤器数组,在请求传递过程中,对请求做一些修改

断言(Predicate):参照 Java8 的新特性Predicate,允许开发人员匹配 HTTP 请求中的任何内容,比如请求头或请求参数,最后根据匹配结果返回一个布尔值。

Predicate 来自于 Java8 的接口。Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。

Predicate 可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。Spring Cloud Gateway 内置了许多 Predict,这些 Predict 的源码在 org.springframework.cloud.gateway.handler.predicate 包中,有兴趣可以阅读一下。

过滤器(Filter):可以在返回请求之前或之后修改请求和响应的内容。

Gateway 过滤器的生命周期:

PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。

POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。

Gateway 过滤器从作用范围可分为两种:

GatewayFilter:应用到单个路由或者一个分组的路由上(需要在配置文件中配置)

GlobalFilter:应用到所有的路由上(无需配置,全局生效)

有两种方式可以实现Gateway路由配置:

准备工作:我们先按照service1服务创建一个service2服务,端口用8003,创建后的项目架构:

service1和service2接口方法如下:

第一种:yml配置

在Gateway项目的yml中加入以下配置:

spring:application:name: gatewaycloud:nacos:discovery:server-addr: 114.115.xxx.xx:8848namespace: 900c8c5e-b442-4b61-abf4-90b640e643eaconfig:server-addr: 114.115.xxx.xx:8848namespace: 900c8c5e-b442-4b61-abf4-90b640e643eaprefix: gatewaygroup: DEFAULT_GROUPfile-extension: yaml# gateway 配置gateway:# 路由数组:指当请求满足什么样的断言时,转发到哪个服务上routes:# 路由唯一标识- id: gateway-service1# 要转发到哪个服务,我们这里不直接写ip:端口的形式,因为一旦服务的域名或IP地址发生修改,路由配置中的 uri 就必须修改# 使用了lb形式,从注册中心负载均衡的获取uriuri: lb://service1# 设置断言predicates:# 满足/service1的请求路径会路由到localhost:8001服务- Path=/service1/**# 过滤器filters:# 去除原始请求路径中的前1级路径,也就是/service1- StripPrefix=1# 路由唯一标识- id: gateway-service2# 要转发到哪个服务uri: lb://service2# 设置断言predicates:# 满足/service1的请求路径会路由到localhost:8001服务- Path=/service2/**# 过滤器filters:# 去除原始请求路径中的前1级路径,也就是/service1- StripPrefix=1

启动项目:

通过网关访问service1服务的接口:

通过网关访问service2服务的接口:

结论:虽然两个服务接口地址一样,但通过网关配置,我们可以根据不同的请求路径前缀来访问不通的服务

第二种:代码配置

通过代码我们可以更加灵活的对Gateway进行配置,面对的场景也更加复杂。

第一步:先把yml中Gateway配置注释

第二步:添加自定义配置类

package com.javacoding.config;import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.stereotype.Component;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;import java.net.URI;
import java.util.*;@Component
public class MyRouteDefinitionRepository implements RouteDefinitionRepository {@Overridepublic Flux<RouteDefinition> getRouteDefinitions() {List<RouteDefinition> routeDefinitions = new ArrayList<>();// service1的route配置RouteDefinition service1 = setService1();// service2的route配置RouteDefinition service2 = setService2();routeDefinitions.add(service1);routeDefinitions.add(service2);return Flux.fromIterable(routeDefinitions);}private RouteDefinition setService2() {RouteDefinition definition = new RouteDefinition();// iddefinition.setId("service2");URI uri = UriComponentsBuilder.fromUriString("lb://service2").build().toUri();// uridefinition.setUri(uri);PredicateDefinition predicate = new PredicateDefinition();predicate.setName("Path");Map<String, String> predicateParams = new HashMap<>(8);predicateParams.put("pattern", "/service2/**");predicate.setArgs(predicateParams);//定义FilterFilterDefinition filter = new FilterDefinition();filter.setName("StripPrefix");Map<String, String> filterParams = new HashMap<>(8);//该_genkey_前缀是固定的,见org.springframework.cloud.gateway.support.NameUtils类filterParams.put("_genkey_0", "1");filter.setArgs(filterParams);definition.setFilters(Collections.singletonList(filter));definition.setPredicates(Collections.singletonList(predicate));return definition;}private RouteDefinition setService1() {RouteDefinition definition = new RouteDefinition();// iddefinition.setId("service1");URI uri = UriComponentsBuilder.fromUriString("lb://service1").build().toUri();// uridefinition.setUri(uri);PredicateDefinition predicate = new PredicateDefinition();predicate.setName("Path");Map<String, String> predicateParams = new HashMap<>(8);predicateParams.put("pattern", "/service1/**");predicate.setArgs(predicateParams);//定义FilterFilterDefinition filter = new FilterDefinition();filter.setName("StripPrefix");Map<String, String> filterParams = new HashMap<>(8);//该_genkey_前缀是固定的,见org.springframework.cloud.gateway.support.NameUtils类filterParams.put("_genkey_0", "1");filter.setArgs(filterParams);definition.setFilters(Collections.singletonList(filter));definition.setPredicates(Collections.singletonList(predicate));return definition;}@Overridepublic Mono<Void> save(Mono<RouteDefinition> route) {return null;}@Overridepublic Mono<Void> delete(Mono<String> routeId) {return null;}
}

第三步:启动项目测试

总结:这些只是基础的配置,实际生产中还会有自定义全局过滤器等。

5、Feign服务调用

5.1、服务调用

当我们在service1调用service2中的接口时,传统的项目我们直接用maven引入service2项目就可以直接调用。但在微服务中,各个项目都是独立存在的,我们如果用http去调用每次都非常繁琐,而且不方便拓展。因此Feign就是解决这个问题。

第一步:创建Feign项目,过程省略,项目结构如下

第二步: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>project_springcloud</artifactId><groupId>org.example</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>feign</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency></dependencies>
</project>

第三步:yml配置

spring:application:name: feigncloud:nacos:discovery:server-addr: 114.115.xxx.xx:8848namespace: 900c8c5e-b442-4b61-abf4-90b640e643eaconfig:server-addr: 114.115.xxx.xx:8848namespace: 900c8c5e-b442-4b61-abf4-90b640e643eaprefix: feigngroup: DEFAULT_GROUPfile-extension: yaml

第四步:写feign客户端接口

package com.javacoding.service;import com.javacoding.service.impl.Service2ClientBack;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;@FeignClient(value = "service2", fallback = Service2ClientBack.class)
public interface Service2Client {@RequestMapping("/test/msg")public String test(@RequestParam("msg") String msg);}

说明:

1. @FeignClient注解标识当前接口是feign调用接口,value代表哪个服务调用接口,这里我们想调用service2服务,所以写service2(为什么写service2,因为service2服务里的配置文件spring.application.name,与他保持一致);fallback是如果服务调用失败,我该怎么处理,这个类就是处理这个问题的。

2. 接口请求路径,请求名和方法与service2要调用的接口保持一致。

package com.javacoding.service.impl;import com.javacoding.service.Service2Client;
import org.springframework.stereotype.Component;/*** 调用失败返回*/
@Component
public class Service2ClientBack implements Service2Client {@Overridepublic String test(String msg) {return "service2服务调用失败!!!";}
}

第五步:在service1通过feign实现service2接口请求响应

1、在pom中加入feign依赖

<!--feign类引用-->
<dependency><groupId>org.example</groupId><artifactId>feign</artifactId><version>1.0-SNAPSHOT</version>
</dependency>
<!--feign服务依赖-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

2、启动类添加@EnableFeignClients注解

package com.javacoding;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;@SpringBootApplication
@EnableFeignClients
public class Service1Application {public static void main(String[] args) {SpringApplication.run(Service1Application.class, args);}
}

3、controller添加调用的方法

package com.javacoding.controller;import com.javacoding.service.Service2Client;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
@RequestMapping("/test")
public class TestController {@Resourceprivate Service2Client service2Client;@GetMapping("/msg")public String test(@RequestParam("msg") String msg) {return "service1:" + msg;}/*** 通过feign调用service2的接口* * @param msg* @return*/@GetMapping("/feign/msg")public String test2(@RequestParam("msg") String msg) {String result = service2Client.test(msg);return "通过feign调用请求返回:" + result;}}

4、测试

总结:我们并没有在service1中引入service2的服务,也实现了调用service2服务中的接口。之后我们想要在微服务中引入其他服务只需写一个某某服务的接口(xxxClient)利用@FeignClient注解指明哪个服务,通过这个接口就可以去调用我们的目标服务的接口。

5.2、服务降级

前面我在@FeignClient注解里加了fallback参数。Fallback是通过Hystrix实现的, 所以需要开启Hystrix,spring boot application.properties文件配置feign.hystrix.enabled=true,这样就开启了Fallback。

service1的nacos中的yml配置:

server:port: 8001feign:hystrix:enabled: true

service2中服务抛出个异常,模拟服务不可用:

package com.javacoding.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/test")
public class TestController {@GetMapping("/msg")public String test(@RequestParam("msg") String msg) {throw new RuntimeException();
//        return "service2:" + msg;}}

测试:

5.3、负载均衡

如果我们service2服务是非常重要的,我们通过会部署好几个防止其中一个崩溃导致服务不可用,那么service1在通过feign调用的时候到底调用了哪一个service2呢?如何把请求进行分配呢?

第一步:先把service2的nacos配置的端口注释掉,改为写在项目bootstrap.yml里面。经过测试发现,如果不写在项目bootstrap.yml里面,后续我们启动两个service2服务的时候会一直用nacos配置里的端口。

spring:application:name: service2cloud:nacos:discovery:server-addr: 114.115.xxx.xx:8848namespace: 900c8c5e-b442-4b61-abf4-90b640e643eaconfig:server-addr: 114.115.xxx.xx:8848namespace: 900c8c5e-b442-4b61-abf4-90b640e643eaprefix: service2group: DEFAULT_GROUPfile-extension: yaml
server:port: 8003

第二步:改造一下service2中的方法,返回信息中加入端口信息,方便区分请求的是哪个服务

package com.javacoding.controller;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.servlet.http.HttpServletRequest;@RestController
@RequestMapping("/test")
public class TestController {@GetMapping("/msg")public String test(@RequestParam("msg") String msg, HttpServletRequest request) {
//        throw new RuntimeException();int serverPort = request.getServerPort();return "service2:" + msg + ",端口:" + serverPort;}}

第三步:启动网关、service1、service2服务,然后复制service2更改端口启动,这样service2服务就启动了两个实例。

所有服务启动后nacos里的实例信息如下:

第四步:测试接口

总结:可以看到我们的请求在8003和8004端口来回切换,这就是默认的轮训策略。

拓展:除了默认的轮训还有哪些策略?

通常我们都是自定义的方式来配置我们的负载均衡策略,这样我们会有更多的操作空间。

在service1中我们自定义配置:

package com.javacoding.config;import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;@Configuration
public class FeignBalanceConfig {@Bean@LoadBalancedpublic RestTemplate getResTemplate() {return new RestTemplate();}//    @Bean
//    public RoundRobinRule getRule() {
//        // 轮训
//        return new RoundRobinRule();
//    }@Beanpublic RandomRule getRule() {//随机策略return new RandomRule();}
}

测试随机策略:

还有其他一些策略,不在一一演示了,配置如下:

@Bean
public AvailabilityFilteringRule getRule() {//首先会过滤掉故障机或者并发链接数超过阈值的服务器.剩余的机器轮询配置return new AvailabilityFilteringRule();
}@Bean
public WeightedResponseTimeRule getRule() {//服务器影响时间越快,则权重越高return new WeightedResponseTimeRule();
}@Bean
public BestAvailableRule getRule() {//最大可用策略,即先过滤出故障服务器后,选择一个当前并发请求数最小的return new BestAvailableRule();
}

ok,以上内容如果都学会并了解那代表你已经可以用springcloud微服务应对90%开发需求了。当然还有Hystrix、Ribbon组件,虽然没讲如何用,但这两个组件Feign都已经很好了集成了,如果你面对的是非常复杂的开发场景,那也可以单独去配置这两个组件(原理都是一样的)。

希望这篇微服务项目可以带你很好的入门~~~

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

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

相关文章

【广州华锐互动】智能楼宇3D数字化展示,实现对建筑物的实时监控和管理

随着科技的不断发展&#xff0c;人们对于生活品质的要求也在不断提高。在这个信息爆炸的时代&#xff0c;如何将复杂的数据以直观、生动的方式呈现给用户&#xff0c;已经成为了一个重要的课题。智能楼宇3D数字化展示作为一种新型的建筑科技&#xff0c;正逐渐成为行业的新宠&a…

【图像分类】【深度学习】【Pytorch版本】VggNet模型算法详解

【图像分类】【深度学习】【Pytorch版本】VggNet模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】VggNet模型算法详解前言VggNet讲解感受野感受野的计算公式3x3的卷积核的使用VggNet模型结构 VGGnet Pytorch代码完整代码总结 前言 Vgg(Visual Geometry Group)是…

养老院展示服务预约小程序的作用是什么

养老院无论在哪个城市都有很高需求度&#xff0c;不少银发人群会因为种种原因而前往&#xff0c;而养老院近些年来各种服务也比较完善&#xff0c;增加了客户信任度及接受度&#xff0c;但对院方来说&#xff0c;也存在着一些痛点&#xff1a; 1、品牌传播服务呈现难 养老院也…

网络运维Day01

文章目录 环境准备OSI七层参考模型什么是协议&#xff1f;协议数据单元(PDU)设备与层的对应关系什么是IP地址&#xff1f;IP地址分类IP的网络位和主机位IP地址默认网络位与主机位子网掩码默认子网掩码查看IP地址安装CISCO汉化CISCO(可选操作) CISCO之PC机器验证通信 CISCSO之交…

PMI-ACP(103:57- 103)

57/103 高绩效敏捷团队的特征 参与式指导有效的决策开放和清晰的沟通价值多样性相互信任管理冲突清楚目标明确定义角色 和 职责协调关系积极的氛围 58/103 创建授权团队 敏捷强调 具备授权和积极性 的自我管理团队&#xff0c;他们需要对项目成果充分负责&#xff0c;授权是…

软考 -- 计算机学习(3)

文章目录 一、软件测试基础1.1 基本概念1.2 软件测试模型1.3 软件测试的分类 二、基于规格说明的测试技术(黑盒)2.1 重要的测试方法1. 等价类划分法2. 边界值法3. 判定表法4. 因果图法 2.2 其他测试方法 三、基于结构的测试技术(白盒)3.1 静态测试3.2 动态测试 一、软件测试基础…

配置阿里云镜像加速器 -docker

1.百度aliyun 2.找到镜像服务ACR 3.搞一个个人版&#xff0c;身份验证一下就行了很简单 4.找到镜像加速器Centos 5.执行下面4条命令&#xff1a;4条命令直接从上面操作文档中粘贴&#xff0c;不容易出错 sudo mkdir -p /etc/docker sudo tee /etc/docker/daemon.json <<…

Win10 + VS017 编译SQLite3.12.2源码

参考&#xff1a; [1] WIN10 VS2019下编译GDAL3.0PROJ6SQLite_gdal 3 win10编译-CSDN博客 [2] 如何编译SQLite-How To Compile SQLite-CSDN博客 如何生成静态库&#xff1a; 参考&#xff1a; WIN10 VS2019下编译GDAL3.0PROJ6SQLite_gdal 3 win10编译-CSDN博客 如何生成exe:…

电动车展示预约小程序的作用如何

电动车可以说是现在出行常见的方法&#xff0c;覆盖年龄广几乎是每家必备&#xff0c;也有不小大小品牌和经销商&#xff0c;市场需求较高&#xff0c;但在实际经营中&#xff0c;对经销商来时也面临着一些痛点&#xff1a; 1、品牌传播产品展示难 不同品牌竞争很大&#xff…

Spark 基础知识点

Spark 基础 本文来自 B站 黑马程序员 - Spark教程 &#xff1a;原地址 什么是Spark 什么是Spark 1.1 定义&#xff1a;Apache Spark是用于大规模数据&#xff08;large-scala data&#xff09;处理的统一&#xff08;unified&#xff09;分析引擎 Spark最早源于一篇论文 Re…

viple入门(五)

&#xff08;1&#xff09;自定义活动 自定义活动&#xff0c;用来创建新的组件、服务、函数或者其他代码模块&#xff0c;使用最多的是创建函数。 函数是对一个功能的封装&#xff0c;在调用的时候执行&#xff0c;没有调用的时候则不执行。函数可能有参数&#xff0c;可能没…

信号发送与处理-上

问题 按下 Ctrl C 后&#xff0c;命令行中的前台进程会被终止。为什么&#xff1f;&#xff1f;&#xff1f; 什么是信号&#xff1f; 信号是一种 "软件中断"&#xff0c;用来处理异步事件 内核发送信号到某个进程&#xff0c;通知进程事件的发送事件可能来自硬件…

基于 golang 从零到一实现时间轮算法 (三)

引言 本文参考小徐先生的相关博客整理&#xff0c;项目地址为&#xff1a; https://github.com/xiaoxuxiansheng/timewheel/blob/main/redis_time_wheel.go。主要是完善流程以及记录个人学习笔记。 分布式版实现 本章我们讨论一下&#xff0c;如何基于 redis 实现分布式版本的…

RuntimeError: Distributed package doesn‘t have NCCL built in

因为windows不支持NCCL backend 已解决 import os os.environ["PL_TORCH_DISTRIBUTED_BACKEND"] "gloo"

TextMate v2.0.23(文本编辑器)

Mac上好用的文本编辑器是哪个&#xff1f;TextMate 2 mac版是Macos上一款文本编辑器&#xff0c;支持大量编程语言并作为开源开发。该软件与“BBEdit”并成为苹果电脑上的EMACS和vim&#xff0c;对于程序员来说非常的适合&#xff0c;可以定制许多贴心的功能。为专业脚本编写者…

基于ruoyi框架项目-部署到服务器上

基于ruoyi框架项目-部署到服务器上 文章目录 基于ruoyi框架项目-部署到服务器上1.前端vue编译&#xff0c;后的dist下内容打包&#xff08;前后端分离版本需要&#xff09;2.后端打包成jar包&#xff08;如果是thymeleaf仅需打包jar&#xff09;3.上传到服务器目录下4. docker部…

2023北京1024城市开发者聚会总结

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

2011年408计网

第33题 TCP/IP 参考模型的网络层提供的是&#xff08;&#xff09;A. 无连接不可靠的数据报服务B. 无连接可靠的数据报服务C. 有连接不可靠的虚电路服务D. 有连接可靠的虚电路服务 本题考查TCP/IP 参考模型的网络层 若网络层提供的是虚电路服务&#xff0c;则必须建立网络层的…

Magic Bullet Suite v2024.0.1

Red Giant Magic Bullet Suite是一套AE视频后期处理软件&#xff0c;适用于Premiere Pro、After Effects等视频编辑软件。它提供了多种精美的视频特效和调色工具&#xff0c;使得视频制作更加专业和出色。 Magic Bullet Suite包括多个插件&#xff0c;其中最为知名的是Magic B…

Flink SQL TopN语句详解

TopN 定义&#xff08;⽀持 Batch\Streaming&#xff09;&#xff1a; TopN 对应离线数仓的 row_number()&#xff0c;使⽤ row_number() 对某⼀个分组的数据进⾏排序。 应⽤场景&#xff1a; 根据 某个排序 条件&#xff0c;计算 某个分组 下的排⾏榜数据。 SQL 语法标准&am…