Spring Cloud简介

1.简介

Spring Cloud是Spring旗下的项目之一,官网地址:http://projects.spring.io/spring-cloud/

Spring最擅长的就是集成,把世界上最好的框架拿过来,集成到自己的项目中。

Spring Cloud也是一样,它将现在非常流行的一些技术整合到一起,实现了诸如:配置管理,服务发现,智能路 由,负载均衡,熔断器,控制总线,集群状态等等功能。其主要涉及的组件包括

Netflix

  • Eureka:注册中心
  • Zuul:服务网关
  • Ribbon:负载均衡
  • Feign:服务调用
  • Hystrix:熔断器

以上只是其中一部分,架构图

3.2 版本

Spring Cloud的版本命名比较特殊,因为它不是一个组件,而是许多组件的集合,他的命名是以A到Z为首字母的一些单词组成(其实是伦敦地铁站的名字):

Spring Clound 和Spring Boot版本对应关系

Release Train Boot Version
Hoxton 2.2x
Greenwich 2.1x
Finchley 2.0x
Edgware 1.5x
Dalston 1.5x

本次采用Greenwich版本

微服务场景模拟

模拟一个服务调用的场景。方便学习后面的课程

1 创建父工程

微服务中需要同时创建多个项目,为了方便课堂演示,先创建一个父工程,后续的工程都以这个工程为父,使用 Maven的聚合和继承。统一管理子工程的版本和配置

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-R80HYYsE-1613811086756)(C:\Users\36610\AppData\Roaming\Typora\typora-user-images\image-20210213140311249.png)]

pom.xml文件

<?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>com.lqh</groupId><artifactId>spring-cloud</artifactId><packaging>pom</packaging><version>1.0-SNAPSHOT</version><modules><module>user-service</module><module>consumer-demo</module><module>eureka-service</module><module>lqh-gateway</module><module>config-server</module></modules><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.5.RELEASE</version><relativePath/></parent><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target><spring-cloud.version>Greenwich.SR1</spring-cloud.version><mapper.starter.version>2.1.5</mapper.starter.version><mysql.version>8.0.23</mysql.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><!-- 通用Mapper启动器 --><dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId><version>${mapper.starter.version}</version></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>${mysql.version}</version></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>

注意:spring cloud和spring boot的版本对应 greenwich版本cloud对应spring boot 2.1x

注意:注意聚合父工程<packaging>pom</packaging>

这里已经毒地大部分要用到的依赖进行了管理,方便后续使用

2 服务提供者

我们新建一个项目,对外提供查询用户的服务。

2.1 创建Module

选中lqh-springcloud,创建子工程

pom.xml文件

<?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>spring-cloud</artifactId><groupId>com.lqh</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>user-service</artifactId><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- 通用Mapper启动器 --><dependency><groupId>tk.mybatis</groupId><artifactId>mapper-spring-boot-starter</artifactId></dependency><!-- mysql驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--jdk11会遇到版本问题,添加下面依赖就可解决--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-bus</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-stream-binder-rabbit</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency></dependencies></project>

项目结构

4.2.2编写配置文件

server:port: 9091
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/springcloudusername: rootpassword: 123456application:name: user-service
mybatis:type-aliases-package: com.lqh.user.pojo

使用Mysql图形界面工具,导入springclound.sql脚本

4.2.3 编写代码文件

启动类

@SpringBootApplication
@MapperScan("com.lqh.mapper ")
@EnableDiscoveryClient
public class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class, args);}
}

实体类


@Data
@Table(name = "tb_user")
public class User{// id@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;// 用户名private String userName;// 密码private String password;// 姓名private String name;// 年龄private Integer age;// 性别,1男性,2女性private Integer sex;// 出生日期private Date birthday;// 创建时间private Date created;// 更新时间private Date updated;// 备注private String note;
}

UserMapper

public interface UserMapper extends Mapper<User> {}

UserService

@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public User queryById(Long id) {return this.userMapper.selectByPrimaryKey(id);}
}

controller

对外提供REST风格web 服务,根据id查询用户

@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/{id}")public User queryById(@PathVariable Long id){return userService.queryById(id);}
}

完成上述代码后的项目结构

4.2.4. 启动并测试

启动项目,访问http://localhost:9091/user/7

5.Eureka注册中心

5.1 Eureka简介

问题分析

在刚才的案例中,user-service对外提供服务,需要对外暴露自己的地址。而consumer(调用者)需要记录服务 提供者的地址。将来地址出现变更,还需要及时更新。这在服务较少的时候并不觉得有什么,但是在现在日益复杂 的互联网环境,一个项目肯定会拆分出十几,甚至数十个微服务。此时如果还人为管理地址,不仅开发困难,将来 测试、发布上线都会非常麻烦,这与DevOps的思想是背道而驰的。

网约车

这就好比是网约车出现以前,人们出门叫车只能叫出租车。一些私家车想做出租却没有资格,被称为黑车。而很多 人想要约车,但是无奈出租车太少,不方便。私家车很多却不敢拦,而且满大街的车,谁知道哪个才是愿意载人 的。一个想要,一个愿意给,就是缺少引子,缺乏管理啊。

此时滴滴这样的网约车平台出现了,所有想载客的私家车全部到滴滴注册,记录你的车型(服务类型),身份信息 (联系方式)。这样提供服务的私家车,在滴滴那里都能找到,一目了然。

此时要叫车的人,只需要打开APP,输入你的目的地,选择车型(服务类型),滴滴自动安排一个符合需求的车到 你面前,为你服务,完美!

Eureka做什么?

Eureka就好比是滴滴,负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉 Eureka,然后Eureka会把符合你需求的服务告诉你。

同时,服务提供方与Eureka之间通过 “心跳”机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服 务列表中剔除

这就实现了服务的自动注册、发现、状态监控。

5.2 原理图

基本架构

  • Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址
  • 提供者:启动后向Eureka注册自己信息(地址,提供什么服务)
  • 消费者:向Eureka订阅服务,Eureka会将对应提供者列表发送给消费者,并定期更新
  • 心跳(续约):提供者定期通过HTTP方式向Eureka刷新自己的状态

工作原理图解析

5.3 入门案例

5.3.1 编写EurekaServer

Eureka是服务注册中心,只做服务注册;自身并不提供服务也不消费服务。可以搭建web工程使用Eureka,可以使用Spring Boot方式搭建

1.pom.xml

<?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>spring-cloud</artifactId><groupId>com.lqh</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>eureka-service</artifactId><properties><maven.compiler.source>11</maven.compiler.source><maven.compiler.target>11</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency></dependencies></project>

2.编写启动类:

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class, args);}
}

3.编写配置:

server:port: 10086spring:application:name: eureka-serviceeureka:client:service-url:#eureka服务器地址,如果做集群,需要指定其他eureka地址defaultZone: ://127.0.0.1:10086/eureka#不注册自己register-with-eureka: false#不拉取服务afetch-registry: false

4.启动服务,并访问:http://127.0.0.1:10086/

5.3.2 服务注册

在服务提供工程user-service上添加Eureka客户端依赖;自动将服务注册到EurekaServer服务地址列表

  1. 添加依赖
     <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>

2.在启动类上开启Eureka客户端功能

通过添加@EnableDiscoveryClient来开启Eureka客户端功能

@SpringBootApplication
@MapperScan("com.lqh.mapper ")
@EnableDiscoveryClient //开启Eureka发现功能
public class UserApplication {public static void main(String[] args) {SpringApplication.run(UserApplication.class, args);}
}

3.编写配置

server:port: 12123
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/bill-managerusername: rootpassword: 123456application:name: bill-service
mybatis:type-aliases-package: com.lqh.beanmapper-locations: classpath:/mappers/*.xml
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka

注意:

  • 这里我们添加了spring.application.name属性来指定应用名称,将来会作为应用的id使用。
  • 不用指定register-with-eureka和fetch-registry,因为默认是true

重启项目,访问Eureka监控页面查看

我们先user-service 服务已经注册了

5.3.3 服务发现

在服务消费工程consumer-demo上添加Eureka客户端依赖;可以使用工具类DiscoveryClient根据服务名称获取对 应的服务地址列表。

1.添加依赖

     <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency>

2.在启动类添加开启Eureka客户端发现的注解

@SpringBootApplication
@EnableDiscoveryClient
public class WebApplication {public static void main(String[] args) {SpringApplication.run(WebApplication.class, args);}@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
}

3.修改配置

spring:application:name: consumer-demo
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka

4.修改代码,用DiscoveryClient类的方法,根据服务名称,获取服务实例:

@RestController
@RequestMapping("/consumer")
public class ConsumerController {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;@GetMapping("/{id}")public User queryById(@PathVariable("id") Long id) {String url = "http://localhost:9091/user/" + id;List<ServiceInstance> serviceInstances = discoveryClient.getInstances("user-service");ServiceInstance serviceInstance = serviceInstances.get(0);url = "http://" + serviceInstance.getHost() + ":" + serviceInstance.getPort() + "/user/"
+ id;return restTemplate.getForObject(url, User.class);}
}

5.Debug跟踪运行:

5.4 Eureka详解

接下来我们详细讲解Eureka的原理及配置

5.4.1 基础架构

Eureka架构中的三个核心角色:

  • 服务注册中心

    Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的eureka-server

  • 服务提供者

    提供服务的应用,可以是Spring Boot应用,也可以是其他任意技术实现,只要对外提供REST风格服务即可。本例中就是我们实现的user-service

  • 服务消费者

    消费应用从注册中心获取服务列表,从而的值每个服务方的信息,知道去哪里调用服务方。本例中就是我们的consumer-demo

5.4.2 高可用的Eureka Server

EurekaServer即服务的注册中心,在刚才的案例中,我们只有一个EurekaServer,事实上EurekaServer也可以是一个集群,形成高可用的Eureka中心。

Eureka Server是一个web应用,可以启动多个实例(配置不同端口)保证Eureka Server的高可用

服务同步

多个Eureka Server之间也会互相注册为服务,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会吧服务的信息同步给集群中的每一个节点,从而实现数据同步。因此,无论客户端访问到Eureka Server集群中的任意一个节点,都可以获取到完整的服务列表信息。

而作为客户端,需要把信息注册到每个Eureka中

如果 三个Eureka,则每一个EurekaServer都需要注册到其他几个Eureka服务中

例如:有三个分别为10086,10087,10088,则:

  • 10086要注册到10087和10088上
  • 10087要注册到10086和10088上
  • 10088要注册到10087和10086上

动手搭建高可用的EurekaServer

我们假设要搭建两条EurekaServer的集群,端口分别为:10086和10087

5.4.3 Eureka客户端和服务端配置

进行一系列的配置:

  • Eureka客户端工程

    • user-service 服务提供

      • 服务地址使用IP方式
      • 续约
    • consumer-demo 服务消费
      • 获取服务地址的频率
  • Eureka服务端工程eureka-server
    • 失效剔除
    • 自我保护

服务提供者要想EurekaServer注册服务,并且完成服务续约等工作。

服务注册

服务提供者在启动时,会检测配置属性中的: eureka.client.register-with-erueka=true 参数是否为true,事实上 默认就是true。如果值确实为true,则会向EurekaServer发起一个Rest请求,并携带自己的元数据信息, EurekaServer会把这些信息保存到一个双层Map结构中 。

  • 第一层Map的Key就是服务id,一般是配置中的spring.application.name属性,user-service
  • 第二层Map的key是服务的实例id。一般host+ serviceId + port,例如: localhost:user-service:8081
  • 值则是服务的实例对象,也就是说一个服务,这样可以同时启动多个不同实例,形成集群。

默认注册时使用的是主机名或者localhost,如果想用ip进行注册,可以在 user-service 中添加配置如下:

eureka:instance:ip-address: 127.0.0.1 #ip地址prefer-ip-address: true #更倾向于使用ip,而不是host名

修改完后先后重启 user-service 和 consumer-demo ;在调用服务的时候就已经变成ip地址;需要注意的是:不是 在eureka中的控制台服务实例状态显示。

服务续约

在注册服务完成以后,服务提供者会维持一个心跳(定时向EurekaServer发起Rest请求),告诉 EurekaServer:“我还活着”。这个我们称为服务的续约(renew);

有两个重要参数可以修改服务续约的行为;可以在 user-service 中添加如下配置项:

eureka:instance:lease-expiration-duration-in-seconds: 90lease-renewal-interval-in-seconds: 30

lease-renewal-interval-in-seconds:服务续约(renew)的间隔,默认为30秒

lease-expiration-duration-in-seconds:服务失效时间,默认值90秒

也就是说,默认情况下每个30秒服务会向注册中心发送一次心跳,证明自己还活着。如果超过90秒没有发送心 跳,EurekaServer就会认为该服务宕机,会从服务列表中移除,这两个值在生产环境不要修改,默认即可

获取服务列表

当服务消费者启动时,会检测 eureka.client.fetch-registry=true 参数的值,如果为true,则会从Eureka Server服 务的列表拉取只读备份,然后缓存在本地。并且 每隔30秒 会重新拉取并更新数据。可以在 consumer-demo 项目 中通过下面的参数来修改:

eureka:client:registry-fetch-interval-seconds: 30

生产环境中,我们不需要修改这个值。

但是为了开发环境下,能够快速得到服务的最新状态,我们可以将其设置小一点。

5.4.5.失效剔除和自我保护

如下的配置都是在Eureka Server服务端进行:

服务下线

当服务进行正常关闭操作时,它会出发一个服务下线的REST请求给EurekaServer,告诉服务中心:我要下线。服务中心接受到请求之后,将该服务置为下线状态

失效剔除

有时我们的服务可能由于内存溢出或网络故障等原因使得服务不能正常的工作,而服务注册中心并未受到“服务下线”的请求。相对于服务提供者的“服务续约”操作,服务注册中心在启动时会创建一个定时任务,默认每隔一段时间(默认60秒))将当前清单中超时(默认为90秒)没有续约的服务剔除,这个操作被称为失效剔除。 可以通过 eureka.server.eviction-interval-timer-in-ms 参数对其进行修改,单位是毫秒。

自我保护

我们关停一个服务,就会在Eureka面板看到一条警告:

这是触发了Eureka的自我保护机制。当一个服务未按时进行心跳续约时,Eureka会统计最近15分钟心跳失败的服 务实例的比例是否超过了85%,当EurekaServer节点在短时间内丢失过多客户端(可能发生了网络分区故障)。在 生产环境下,因为网络延迟等原因,心跳失败实例的比例很有可能超标,但是此时就把服务剔除列表并不妥当,因 为服务可能没有宕机。Eureka就会把当前实例的注册信息保护起来,不予剔除。生产环境下这很有效,保证了大多 数服务依然可用。

但是这给我们的开发带来了麻烦,因此开发阶段我们都会关闭自我保护

eureka:server:enable-self-preservation : false #关闭自我保护模式(缺省为打开)eviction-interval-timer-in-ms: 1000 # 扫描失效服务的间隔时间(缺省为60*1000ms)

小结:

  • user-service
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eurekainstance:# 更倾向使用ip地址,而不是host名prefer-ip-address: true# ip地址ip-address: 127.0.0.1# 续约间隔,默认30秒lease-renewal-interval-in-seconds: 5# 服务失效时间,默认90秒lease-expiration-duration-in-seconds: 5
  • consumer-demo
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka# 获取服务地址列表间隔时间,默认30秒registry-fetch-interval-seconds: 10
  • eureka-server
eureka:server:# 服务失效剔除时间间隔,默认60秒eviction-interval-timer-in-ms: 60000# 关闭自我保护模式(默认是打开的)enable-self-preservation: false

很有效,保证了大多 数服务依然可用。

但是这给我们的开发带来了麻烦,因此开发阶段我们都会关闭自我保护

eureka:server:enable-self-preservation : false #关闭自我保护模式(缺省为打开)eviction-interval-timer-in-ms: 1000 # 扫描失效服务的间隔时间(缺省为60*1000ms)

小结:

  • user-service
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eurekainstance:# 更倾向使用ip地址,而不是host名prefer-ip-address: true# ip地址ip-address: 127.0.0.1# 续约间隔,默认30秒lease-renewal-interval-in-seconds: 5# 服务失效时间,默认90秒lease-expiration-duration-in-seconds: 5
  • consumer-demo
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka# 获取服务地址列表间隔时间,默认30秒registry-fetch-interval-seconds: 10
  • eureka-server
eureka:server:# 服务失效剔除时间间隔,默认60秒eviction-interval-timer-in-ms: 60000# 关闭自我保护模式(默认是打开的)enable-self-preservation: false

Spring Cloud -Eureka 注册中心配置相关推荐

  1. spring cloud搭建_Spring Cloud Eureka 注册中心集群搭建,Greenwich 最新版!

    Spring Cloud 的注册中心可以由 Eureka.Consul.Zookeeper.ETCD 等来实现,这里推荐使用 Spring Cloud Eureka 来实现注册中心,它基于 Netfl ...

  2. 3.spring cloud + zookeeper注册中心 + Feign调用案例

    3.spring cloud + zookeeper注册中心 + Feign调用案例 3.1.pom.xml定义 <?xml version="1.0" encoding=& ...

  3. Spring Cloud 服务注册中心Eureka

    Eureka介绍 在Spring Cloud Netflix 整合技术栈中,Eureka既可以作为服务注册中心也可以用于服务发现对整个微服务架构起着最核心的整合作用. Eureka是基于REST(Re ...

  4. Spring Cloud ---02-- Eureka注册中心

    Eureka 注册中心 作用:服务注册和发现 提供者(Provider) 向注册中心注册自己的地址 消费者(Consumer) 从注册中心发现其他服务 eureka的运行机制 注册 - 一次次反复连接 ...

  5. (十六)Alian 的 Spring Cloud Eureka 集群配置(主机名方式)

    目录 一.背景 二.maven依赖 三.主类 四.Eureka服务配置 五.启动服务 5.1 服务1效果图(eureka-server1.com) 5.2 服务2效果图(eureka-server2. ...

  6. 【Spring Cloud】注册中心-Nacos

    1.名字的由来 前四个字母分别为 Naming 和 Configuration 的前两个字母,最后的 s 为 service 2.是什么 Nacos是一个更易于构建云原生应用的动态服务发现.配置管理和 ...

  7. 【065】Spring Cloud服务注册中心双节点集群,使用Eureka实现,以IP方式配置,基于Spring Cloud的Camden SR5版本

    Spring Cloud 封装了 Netflix 公司开发的 Eureka 模块来实现服务注册和发现.Eureka 采用了 C-S 的设计架构.Eureka Server 作为服务注册功能的服务器,它 ...

  8. 【Spring框架家族】Spring Cloud Eureka 之常用配置解析(转载)

    1. 配置项解析 1.1 通用配置 # 应用名称,将会显示在Eureka界面的应用名称列 spring.application.name=config-service# 应用端口,Eureka服务端默 ...

  9. Spring Cloud的注册中心和服务者,消费者的构建

    注册中心Eureka: 新建项目stu-eureka: StuEurekaApplication: package com.demo.stueureka;import org.springframew ...

最新文章

  1. 南阳汉诺塔 一 java_南阳明清移民记.pdf
  2. 30幅非常漂亮的微距摄影作品欣赏
  3. Linux驱动之平台设备
  4. 到底是32位系统运行快还是64位系统快
  5. Laravel 打造一个完整的项目
  6. ubuntu15.04 php版本,在ubuntu下安装php版本问题
  7. WebAPI——自动生成帮助文档
  8. 计算机二级vb操作题如何给分,计算机二级vb操作题.docx
  9. 基于Protostuff的通用序列化、反序列化功能实现
  10. 计算机主机报警 声,电脑开机报警声音大全
  11. HTTP长连接---requests的长连接
  12. uva10105 - Polynomial Coefficients(多项式系数)
  13. 对汽车供应商的评估需要哪些数据?
  14. 7-1 评委打分 (5分)
  15. 汉诺塔——老夫不管什么分析不分析,直接粗暴
  16. 树莓派Pico直流电机接口技术及PWM电机调速控制MicroPython编程
  17. ArcGIS Pro添加在线底图
  18. hive编程中的细枝末节
  19. 在 JavaScript 中按字母顺序排序 - 如何在 JS 中按名称排序
  20. mindspore ST调试报错 RunTimeError

热门文章

  1. F - Wi Know Kattis - wiknow
  2. python利用opencv去除图片logo_python 基于opencv去除图片阴影
  3. html如何打包文件发送,手把手教你webpack如何打包才能输出最优生产文件
  4. oppo 手机侧滑快捷菜单_oppo手机怎么截图 oppo手机快捷键截屏步骤【介绍】
  5. 【python】python字符串占位符
  6. 小程序生命周期 页面生命周期及小程序生命周期
  7. HTML CSS 贵美商城网页布局
  8. 90后树友加入至善林钉钉合种的体验“不积小流,无以成江海”
  9. Web视觉设计师培训视频教程
  10. 解决nginx重启出现没有nginx.pid文件的报错提示