Dubbo在国内有着非常大的用户群体,但是其周边设施与组件相对来说并不那么完善。很多开发者用户又很希望享受Spring Cloud的生态,因此也会有一些Spring Cloud与Dubbo一起使用的案例与方法出现,但是一直以来大部分Spring Cloud整合Dubbo的使用方案都不完善。直到Spring Cloud Alibaba的出现,才得以解决这样的问题。

​ SpringCloud Alibaba是阿里巴巴公司基于Spring Cloud所开发的一套微服务框架集,本文阐述了SpringCloud Alibaba应用于生产实践的一种架构方案,此方案即可享有Dubbo RPC服务通信的优势,也可使用Spring Cloud RESTful接口的通用性。

1 总体结构

系统架构图如下:

组件说明:

API网关 :系统统一入口,屏蔽架构内部结构,统一安全拦截,采用Zuul实现。

application-1 :应用1,模拟应用,提供http接口服务。

service-1 :微服务1,模拟微服务,提供dubbo接口服务。

service-2 :微服务2,模拟微服务,提供dubbo接口服务。

调用流程:

​ 所有访问系统的请求都要经过网关,网关转发Http请求至application-1,application-1使用dubbo调用service1完成自身业务,而后sevice1调用service2完成自身业务。至此,完成所有组件贯穿。

架构中application与sevice的区别是什么?

  • service提供了基础服务功能;application组装基础服务功能,提供给用户直接可用的业务。
  • service服务粒度小、功能基础,不易发生改变;application提供上游业务功能,紧贴业务需求,容易发生改变。
  • 形成service支撑application的整体架构,增加多变的application甚至不需要变动service。

2 工程结构说明

采用maven工程,结构如下:

nacos-micro-service   整体父工程├─api-gateway         API网关,端口:56010├─application-1          应用1,端口:56020├─service-1          服务1父工程│  ├─service-1-api     服务1API│  └─service-1-server 服务1实现,端口:56030  └─service-2          服务2父工程├─service-2-api    服务2API└─service-2-server 服务2实现,端口:56040

3 创建父工程

​ 创建 artifactId 名为 nacos-micro-service 的 Maven 工程,此父工程继承nacos-discovery父工程,间接指定了Spring boot、spring cloud 以及spring-cloud-alibaba的依赖版本。

<parent><artifactId>nacos-discovery</artifactId><groupId>com.pbteach.nacos</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>nacos-micro-service</artifactId><packaging>pom</packaging>

nacos-discovery的pom.xml如下:

<groupId>com.pbteach.nacos</groupId>
<artifactId>nacos-discovery</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version>
</properties><dependencyManagement><dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>2.1.0.RELEASE</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Greenwich.RELEASE</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.1.3.RELEASE</version><type>pom</type><scope>import</scope></dependency></dependencies>
</dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins>
</build>

4 实现application1

application1属于应用层,提供http接口服务。

(1)初始化 application-1 Maven 工程

<artifactId>application-1</artifactId>
<dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

(2)实现 application-1 功能

package com.pbteach.microservice.application1.controller;@RestController
public class Application1Controller {@GetMapping("/service")public String service(){return "test" ;}
}

(3) application1 配置

纯粹的dubbo服务消费者,配置看起来更简单。

定义bootstrap.yml

server:port: 56020 #启动端口 命令行注入servlet:context-path: /application1spring:application:name: application1main:allow-bean-definition-overriding: true # Spring Boot 2.1 需要设定cloud:nacos:discovery:server-addr: 127.0.0.1:8848namespace: c67e4a97-a698-4d6d-9bb1-cfac5f5b51c4cluster-name: DEFAULTconfig:server-addr: 127.0.0.1:8848 # 配置中心地址file-extension: yamlnamespace: c67e4a97-a698-4d6d-9bb1-cfac5f5b51c4 # 开发环境group: NACOS_MICROSERVICE_GROUP # xx业务组

(4) application1 启动

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

Service1Bootstrap 启动后,应用 application1 将出现在 Nacos 控制台界面。

5 实现 Service1

5.1 定义父工程

定义service1父工程,pom.xml如下:

<parent><artifactId>nacos-micro-service</artifactId><groupId>com.pbteach.nacos</groupId><version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion><artifactId>Service1</artifactId>

5.2 定义service-1-api

为了方便其它服务调用dubbo服务,专门定义api工程,此工程将作为jar被其它工程依赖。

定义service-1-api工程,pom.xml如下:

<parent><artifactId>Service1</artifactId><groupId>com.pbteach.nacos</groupId><version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion><artifactId>service-1-api</artifactId>

定义服务接口:

package com.pbteach.microservice.service1.api;public interface ConsumerService {public String service();
}

5.3 实现service-1-server

(1)初始化 service-1-server Maven 工程

与服务提供方 Maven工程类似,需添加相关 Maven 依赖:

<parent><artifactId>Service1</artifactId><groupId>com.pbteach.nacos</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>service-1-server</artifactId>
<dependencies><dependency><groupId>com.pbteach.nacos</groupId><artifactId>service-1-api</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-dubbo</artifactId></dependency>
</dependencies>

(2)实现 Dubbo 服务

package com.pbteach.microservice.service1.service;
@org.apache.dubbo.config.annotation.Service
public class ConsumerServiceImpl implements ConsumerService {@Overridepublic String service() {return "Consumer invoke " ;}
}

注意:使用@org.apache.dubbo.config.annotation.Service标记dubbo服务

(3)配置 Dubbo 服务

Service2 作为Dubbo服务消费方配置与服务提供方类似,注意,service1不仅是消费方,同时还是服务提供方:

server:port: ${port:56030} #启动端口 命令行注入spring:application:name: service1main:allow-bean-definition-overriding: true # Spring Boot 2.1 需要设定cloud:nacos:discovery:server-addr: 127.0.0.1:8848namespace: c67e4a97-a698-4d6d-9bb1-cfac5f5b51c4cluster-name: DEFAULTconfig:server-addr: 127.0.0.1:8848 # 配置中心地址file-extension: yamlnamespace: c67e4a97-a698-4d6d-9bb1-cfac5f5b51c4 # 开发环境group: NACOS_MICROSERVICE_GROUP # xx业务组
dubbo:scan:# dubbo 服务扫描基准包base-packages: com.pbteach.microserviceprotocol:# dubbo 协议name: dubbo# dubbo 协议端口port: ${dubbo_port:20881}registry:address: nacos://127.0.0.1:8848application:qos-enable: false #dubbo运维服务是否开启consumer:check: false  #启动时就否检查依赖的服务

以上 YAML 内容,dubbo开头的为dubbo服务 的配置:

  • dubbo.scan.base-packages : 指定 Dubbo 服务实现类的扫描基准包,将@org.apache.dubbo.config.annotation.Service注解标注的service暴露为dubbo服务。
  • dubbo.protocol : Dubbo 服务暴露的协议配置,其中子属性 name 为协议名称,port 为dubbo协议端口

可以指定多协议,如:dubbo.protocol.rmi.port=1099

  • dubbo.registry : Dubbo 服务注册中心配置,其中子属性 address 的值 “nacos://127.0.0.1:8848”,说明dubbo服务注册到nacos

相当于原生dubbo的xml配置中的 <dubbo:registry address="10.20.153.10:9090" />

上半部分为SpringCloud的相关配置:

  • spring.application.name : Spring 应用名称,用于 Spring Cloud 服务注册和发现。

该值在 Dubbo Spring Cloud 加持下被视作 dubbo.application.name,因此,无需再显示地配置 dubbo.application.name

  • spring.cloud.nacos.discovery : Nacos 服务发现与注册配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口
  • spring.cloud.nacos.config : Nacos 配置中心配置,其中子属性 server-addr 指定 Nacos 服务器主机和端口。

(4)启动服务消费方应用

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

Service1Bootstrap 启动后,应用 service1 将出现在 Nacos 控制台界面。

启动成功,观察nacos服务列表

6 实现 application1调用Service1

现在service1已暴露dubbo服务并注册到nacos中,下边实现application1调用service1

6.1 引用service1

下边在application1中引用service1

在pom.xml中引入service-1-api的依赖

<dependency><groupId>com.pbteach.nacos</groupId><artifactId>service-1-api</artifactId><version>1.0-SNAPSHOT</version>
</dependency>

引入 spring-cloud-starter-dubbo依赖,它会根据接口生成代理对象

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

6.2 实现远程调用

@RestController
public class Application1Controller {@org.apache.dubbo.config.annotation.Referenceprivate ConsumerService consumerService;@GetMapping("/service")public String service(){return "test" + consumerService.service();}
}

Note:注意:这里的@Reference注解是org.apache.dubbo.config.annotation.Reference

测试:

请求:http://localhost:56020/application1/service

consumerService正常生成代理对象,service1被调用。

7 实现 Service2

​ 如上面设计所示,Service2需要暴露dubbo接口以供service1消费,若想在Spring cloud Alibaba中集成并使用dubbo。

7.1 定义父工程

定义service2父工程,pom.xml如下:

<parent><artifactId>nacos-micro-service</artifactId><groupId>com.pbteach.nacos</groupId><version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion><artifactId>Service2</artifactId>

7.2 定义service-2-api

​ 定义service-2-api工程,pom.xml如下:

<parent><artifactId>Service2</artifactId><groupId>com.pbteach.nacos</groupId><version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion><artifactId>service-2-api</artifactId>

​ 并定义服务接口,Dubbo 服务接口是服务提供方与消费方的远程通讯契约,通常由普通的 Java 接口(interface)来声明,如 ProviderService 接口:

package com.pbteach.microservice.service2.api;
public interface ProviderService {String service();
}

7.3 实现service-2-server

(1)初始化 service-2-server Maven 工程

首先,创建 artifactId 名为 service-2-server 的 Maven 工程,并在其 pom.xml 文件中增添 Dubbo Spring Cloud 必要的依赖:

<parent><artifactId>Service2</artifactId><groupId>com.pbteach.nacos</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>service-2-server</artifactId>
<dependencies><dependency><groupId>com.pbteach.nacos</groupId><artifactId>service-2-api</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-dubbo</artifactId></dependency>
</dependencies>

以上依赖 artifact 说明如下:

  • service-2-api : 提供 ProviderService 接口的 artifact
  • spring-boot-starter-web : Spring Boot starter artifact,间接引入 spring-boot artifact
  • spring-cloud-starter-dubbo : Dubbo Spring Cloud Starter artifact,间接引入 dubbo-spring-boot-starter 等 artifact
  • spring-cloud-starter-alibaba-nacos-discovery : Nacos Spring Cloud 服务注册与发现 artifact

(2)实现 Dubbo 服务

ProviderService 作为暴露的 Dubbo 服务接口,服务提供方 service-2-server 需要将其实现:

package com.pbteach.microservice.service2.service;@org.apache.dubbo.config.annotation.Service
public class ProviderServiceImpl implements ProviderService {@Overridepublic String service() {return "Provider invoke";}
}

其中,@org.apache.dubbo.config.annotation.Service 是 Dubbo 服务注解,仅声明该 Java 服务(本地)实现为 Dubbo 服务。 因此,下一步需要将其配置 Dubbo 服务(远程)。

(3)配置 Dubbo 服务

在暴露 Dubbo 服务方面,推荐开发人员外部化配置的方式,即指定 Java 服务实现类的扫描基准包。

Dubbo Spring Cloud 继承了 Dubbo Spring Boot 的外部化配置特性,也可以通过标注 @DubboComponentScan 来实现基准包扫描。

同时,Dubbo 远程服务需要暴露网络端口,并设定通讯协议,完整的 YAML 配置如下所示:

server:port: ${port:56040} #启动端口 命令行注入
spring:application:name: service2main:allow-bean-definition-overriding: true # Spring Boot 2.1 需要设定cloud:nacos:discovery:server-addr: 127.0.0.1:8848namespace: c67e4a97-a698-4d6d-9bb1-cfac5f5b51c4cluster-name: DEFAULTconfig:server-addr: 127.0.0.1:8848 # 配置中心地址file-extension: yamlnamespace: c67e4a97-a698-4d6d-9bb1-cfac5f5b51c4 # 开发环境group: NACOS_MICROSERVICE_GROUP # xx业务组
dubbo:scan:# dubbo 服务扫描基准包base-packages: com.pbteach.microserviceprotocol:# dubbo 协议name: dubbo# dubbo 协议端口( -1 表示自增端口,从 20880 开始)port: ${dubbo_port:20891}registry:address: nacos://127.0.0.1:8848application:qos-enable: falseconsumer:check: false

(4)启动服务提供方应用

Dubbo Spring Cloud 引导类与普通 Spring Cloud 应用并无差别,如下所示:

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

在引导 Service2Bootstrap 之前,请提前启动 Nacos 服务器。 当 Service2Bootstrap 启动后,应用 service2 将出现在 Nacos 控制台界面。

8 实现service1调用service2

8.1 引用service2

在service2中添加service1的依赖:

<dependency><groupId>com.pbteach.nacos</groupId><artifactId>service-2-api</artifactId><version>1.0-SNAPSHOT</version>
</dependency>

8.2 实现远程调用

@org.apache.dubbo.config.annotation.Service
public class ConsumerServiceImpl implements ConsumerService {@ReferenceProviderService providerService;public String service() {return "Consumer invoke | "+providerService.service();}
}

测试:

请求:http://localhost:56020/application1/service

application1调用service1,service1调用service2

9 实现api-gateway

9.1 Zuul介绍

什么是网关?

​ 原来的单体架构,所有的服务都是本地的,UI可以直接调用,现在按功能拆分成独立的服务,跑在独立的一般都在独立的虚拟机上的 Java进程了。客户端UI如何访问?他的后台有N个服务,前台就需要记住管理N个服务,一个服务下线/更新/升级,前台就要重新部署,这明显不服务我们拆分的理念,特别当前台是移动应用的时候,通常业务变化的节奏更快。另外,N个小服务的调用也是一个不小的网络开销。

​ 有了网关作为服务统一入口,就可以避免上述问题,不仅如此,服务网关是在微服务前边设置一道屏障,请求先到服务网关,网关会对请求进行过虑、校验、路由等处理。有了服务网关可以提高微服务的安全性,网关校验请求的合法性,请求不合法将被拦截,拒绝访问。

  • 提供统一服务入口,让微服务对前台透明
  • 聚合后台的服务,节省流量,提升性能
  • 提供安全,过滤,流控等API管理功能

什么是Zuul?

​ Spring Cloud Zuul是整合Netflix公司的Zuul开源项目实现的微服务网关,它实现了请求路由、负载均衡、校验过虑等 功能。

官方:https://github.com/Netflix/zuul

Zuul与Nginx怎么配合使用?

Zuul与Nginx在实际项目中需要配合使用,如下图,Nginx的作用是反向代理、负载均衡,Zuul的作用是保障微服务的安全访问,拦截微服务请求,校验合法性及负载均衡。

9.2 搭建网关工程

初始化 api-gateway Maven 工程

<parent><artifactId>nacos-micro-service</artifactId><groupId>com.pbteach.nacos</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>api-gateway</artifactId>
<dependencies><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-zuul</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>
</dependencies>

9.3 api-gateway配置

server:port: 56010 #启动端口 命令行注入spring:application:name: api-gatewaymain:allow-bean-definition-overriding: true # Spring Boot 2.1 需要设定cloud:nacos:discovery:server-addr: 127.0.0.1:8848namespace: c67e4a97-a698-4d6d-9bb1-cfac5f5b51c4cluster-name: DEFAULTconfig:server-addr: 127.0.0.1:8848 # 配置中心地址file-extension: yamlnamespace: c67e4a97-a698-4d6d-9bb1-cfac5f5b51c4 # 开发环境group: NACOS_MICROSERVICE_GROUP # xx业务组

​ 网关的路由配置采用nacos远程配置,在nacos控制台开发环境中新增api-gateway.yaml配置集,配置组为TEST_GROUP,配置内容如下:

zuul:routes:application1:stripPrefix: falsepath: /application1/**

将请求为/application1/开头的请求路由至application1服务,保留请求url中的/application1/

(4) api-gateway启动

注意在启动类上使用@EnableZuulProxy注解标识此工程为Zuul网关,启动类代码如下:

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

Service1Bootstrap 启动后,应用 api-gateway 将出现在 Nacos 服务列表中。

测试:

通过网关(api-gateway)请求Application1应用,Application1的业务实现又贯穿service1、service2,访问http://127.0.0.1:56010/application1/service ,将得到如下结果:

10 深入学习

讲义:http://www.pbteach.com/post/java_distribut/nacos-discovery/

视频:http://www.pbteach.com/post/java_distribut/subject_nacos/

springcloudalibaba 架构图_Spring Cloud Alibaba 架构实战相关推荐

  1. nacos 负载策略_Spring Cloud Alibaba:Nacos 作为注册中心和配置中心使用

    Spring Cloud Alibaba 致力于提供微服务开发的一站式解决方案,Nacos 作为其核心组件之一,可以作为注册中心和配置中心使用,本文将对其用法进行详细介绍. SpringCloud实战 ...

  2. gateway sentinel 熔断 不起作用_Spring Cloud Alibaba集训营第五天(服务熔断和限流)

    前言:为什么需要流控降级 我们的生产环境经常会出现一些不稳定的情况,如: 大促时瞬间洪峰流量导致系统超出最大负载,load 飙高,系统崩溃导致用户无法下单 "黑马"热点商品击穿缓存 ...

  3. 效率神器,阿里P8大牛手写Spring cloud Alibaba(实战派)终级手册

    前两天,一位前同事告诉我一个好消息:他进阿里了. 很为他感到高兴,但同时也觉得这很正常,当年我部门内的小伙伴,有不少人去了阿里.京东 .小米的. 我们当时算是国内第一批使用微服务架构的团队了,小伙伴们 ...

  4. Linux启动nacos成功日志_Spring Cloud Alibaba基础教程:使用Nacos作为配置中心

    通过本教程的前两篇: <Spring Cloud Alibaba基础教程:使用Nacos实现服务注册与发现> <Spring Cloud Alibaba基础教程:支持的几种服务消费方 ...

  5. 异构服务器 微服务_Spring Cloud Alibaba Sidecar 多语言微服务异构

    Spring Cloud Alibaba Sidecar 介绍 自 Spring Cloud Alibaba 2.1.1 版本后增加了 spring-cloud-alibaba-sidecar 模块作 ...

  6. eureka需要替换吗_Spring Cloud Alibaba迁移指南1:零代码从Eureka迁移到Nacos

    作者:得少,校对:周立. 在本号首发,欢迎转载. Spring Cloud官方宣布Spring Cloud Netflix进入维护状态,后续不再会有新的功能已成为事实. 作为开发者,如何使用极简的方式 ...

  7. com 组件调用不起来_Spring Cloud Alibaba训练营 —— 分布式服务调用

    注意:用手机查看排版可能不太友好, 1. 简介 在<Spring Cloud Alibaba 服务注册与发现>篇中曾提到,Spring Cloud Alibaba Nacos Discov ...

  8. com 组件调用不起来_Spring Cloud Alibaba,分布式服务调用(四)

    1. 简介 在<Spring Cloud Alibaba 服务注册与发现>篇中曾提到,Spring Cloud Alibaba Nacos Discovery 能无缝整合 Spring C ...

  9. dcom配置_spring cloud 二代架构依赖组件 全配置放送

    一 背景介绍 先来看一下我们熟悉的第一代 spring cloud 的组件 spring cloud 现在已经是一种标准了,各公司可以基于它的编程模型编写自己的组件 ,比如Netflix.阿里巴巴都有 ...

  10. 文件服务器 架构图,传奇世界服务端架构图(说明文件),适合新手看

    WolServer(服务器目录) │ ├-DB(数据库) │├GameData.DB (人物属性和帐号数据文件) │└GameLoad.DB (20110622引擎以后的数据库,所有数据合并后的文件) ...

最新文章

  1. OpenCV+python:色彩空间转换及色彩通道的分离和合并
  2. 阿里云EMR异步构建云HBase二级索引
  3. 成功解决TypeError: unhashable type: 'numpy.ndarray'
  4. C++中随机函数rand()和srand()的用法
  5. PHP XML和数组互相转换
  6. 创建 Robotium 测试工程
  7. 深入理解DPDK程序设计|Linux网络2.0
  8. JDBC连接数据库教程,postgreSQL
  9. Mac OS 查看系统版本信息/硬件信息的命令
  10. 前端学习(2880):数据代理和劫持
  11. REST与RESTful
  12. Ubuntu 11.04下最流行的17款应用(linux在中国市场的占有率好像只有0.1几%)
  13. vue页面锚文本_Vue如何实现锚点定位功能?
  14. ASP.NET 前端Ajax获取数据并刷新
  15. php期末考试题机考_phP基础知识期末考试题
  16. 一个意想不到的CDO.Message 错误
  17. 直播程序源码更简单的搭建方法
  18. 如何迈出客户拜访的第一步
  19. pdf论文中visio画的图出现Times New Roman 字体未嵌入
  20. SQLServer数据库压缩与数据库日志压缩

热门文章

  1. 【转】Nutch源代码研究 网页抓取 数据结构
  2. 教程 | 如何使用Docker、TensorFlow目标检测API和OpenCV实现实时目标检测和视频处理
  3. 好风凭借力,送我上青云!
  4. python opencv图片合成视频
  5. AutoCAD2020修改 图层名称
  6. 190314每日一句
  7. 181024词霸有道扇贝每日一句
  8. Atitit 架构之道 之 可读性可维护性架构之道 提升效率架构之道 attilax著 艾龙 著 1.1. Hybrid架构 1 1.2. 分层架构是使用最多的架构模式 Layers模式 也称Tie
  9. Atitit html5.1 新特性attilax总结
  10. Atitit.java c++指针使用总结O7