大纲 前言 学习资源 互联网架构的介绍 大型互联网项目架构的特点
用户多 流量大 并发高 海量数据 易受攻击 功能繁琐 更新频繁 大型互联网项目架构的目标
高性能 :提供快速的访问体验。高并发 :支持大量用户同时在线使用。高可用 :网站服务一直可以正常访问。可伸缩 :通过硬件增加 / 减少,提高 / 降低系统的处理能力。高可扩展 :系统间耦合低,方便地通过新增 / 移除方式,增加 / 减少新的功能 / 模块。安全性 :提供网站安全访问、数据加密、安全存储等策略。敏捷性 :随需应变,快速响应。衡量大型网站的性能指标
响应时间 :指执行一个请求从开始到最后收到响应数据所花费的总体时间并发数 :指系统同时能处理的请求数量并发请求数 :也称为 QPS(QueyPerSecond),指每秒有多少个请求。并发连接数 :指的是客户端向服务器发起请求,并建立了 TCP 连接。每秒服务器连接的总 TCP 数量。并发用户数 :单位时间内有多少个用户。吞吐量 :指单位时间内系统能处理的请求数量 QPS :每秒查询数(Query Per Second) TPS :每秒事务数(Transactions Per Second)一个事务是指一个客户端向服务器发送请求,然后服务器做出反应的过程。客户端在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数。 一个页面的一次访问,只会形成一个 TPS。但是一次页面请求,可能会产生多次对服务器的请求(比如请求 CSS、JS、HTML 资源),这就会有产生多个 QPS。 QPS >= 并发连接数 >= TPS 分布式系统的概念 集群和分布式的概念(图解 )
集群 :很多 “人” 一起,干一样的事。分布式 :很多 “人” 一起,干不一样的事。这些不一样的事,合起来是一件大事。一个大的业务系统,拆分为多个小的业务模块,这些业务模块分别部署在不同的服务器上。 单体架构的部署
集群架构的部署
分布式架构的部署
特别注意
在企业的生产环境中,集群和分布式是并存的,两者并不是分开的。
Dubbo 简介 Dubbo 是阿里巴巴公司开源的一个高性能、轻量级的 Java RPC 框架。 Dubbo 致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。 Dubbo 的功能 核心功能
服务治理
Dubbo 的架构
Dubbo 的特点 Dubbo 的架构具有以下几个特点,分别是连通性、健壮性、伸缩性、以及面向未来架构的升级性。
Dubbo 的依赖
Dubbo 的核心特性
Dubbo 的调用关系 (1) 服务容器负责启动、加载、运行服务提供者。 (2) 服务提供者在启动时,向注册中心注册自己提供的服务。 (3) 服务消费者在启动时,向注册中心订阅自己所需的服务。 (4) 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 (5) 服务消费者,从提供者地址列表中,基于软负载均衡算法,选择一个服务提供者进行调用;如果调用失败,再选择另一个服务提供者进行调用。 (6) 服务消费者和服务提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。 Dubbo 使用 Dubbo 的配置方式 Dubbo 提供了以下三种配置方式,推荐的配置方式是 集成 Spring XML
。
使用 Dubbo 注解
使用简单,有一定的侵入性,实现类需要依赖 Dubbo 提供的注解 集成 Spring XML
使用稍显麻烦,但是可以做到无侵入性,方便以后改用其他 RPC 框架 使用原生 API
Dubbo 的使用方式 服务提供端
(1) 独立的服务(以普通的 Java 程序形式) (2) 集成在应用中(在应用中增加远程服务能力) 消费客户端
(1) 在应用中调用远程服务 (2) 也可以是在服务提供者中调用远程服务 比如:在 Spring 项目中,基于 XML 方式使用 Dubbo,如下图所示
Dubbo 快速入门 XML 方式使用 Dubbo 提示
本节将在 Spring 项目中,基于 XML 使用 Dubbo,完整的案例代码可以直接从 GitHub 下载对应章节 dubbo-lesson-01
。
项目结构
引入依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 <properties > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <maven.compiler.source > 1.8</maven.compiler.source > <maven.compiler.target > 1.8</maven.compiler.target > <spring.version > 5.3.31</spring.version > <dubbo.version > 2.7.8</dubbo.version > <netty.version > 4.1.33.Final</netty.version > <curator.version > 3.3.0</curator.version > <commons-lang3.version > 3.4</commons-lang3.version > <slf4j.version > 1.7.36</slf4j.version > <logback.version > 1.2.12</logback.version > </properties > <dependencies > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-core</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.apache.dubbo</groupId > <artifactId > dubbo</artifactId > <version > ${dubbo.version}</version > </dependency > <dependency > <groupId > io.netty</groupId > <artifactId > netty-all</artifactId > <version > ${netty.version}</version > </dependency > <dependency > <groupId > org.apache.curator</groupId > <artifactId > curator-recipes</artifactId > <version > ${curator.version}</version > </dependency > <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-lang3</artifactId > <version > ${commons-lang3.version}</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-api</artifactId > <version > ${slf4j.version}</version > </dependency > <dependency > <groupId > ch.qos.logback</groupId > <artifactId > logback-classic</artifactId > <version > ${logback.version}</version > </dependency > </dependencies >
日志配置 1 2 3 4 5 6 7 log4j.rootLogger =DEBUG, console log4j.appender.console =org.apache.log4j.ConsoleAppender log4j.appender.console.layout =org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern =%d{ISO8601} %-5p [%t] %c{1} - %m%n
公共接口 1 2 3 4 5 public interface DemoService { String sayHello (String name) ; }
服务提供者 1 2 3 4 5 6 7 8 public class DemoServiceImpl implements DemoService { @Override public String sayHello (String name) { return "Hello " + name; } }
1 2 3 4 5 6 7 8 9 10 public class ProviderApplication { public static void main (String[] args) throws IOException { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("provider.xml" ); context.start(); System.in.read(); context.close(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo ="http://dubbo.apache.org/schema/dubbo" xsi:schemaLocation =" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd" > <dubbo:application name ="dubbo-provider-application" > <dubbo:parameter key ="qos.enable" value ="true" /> <dubbo:parameter key ="qos.port" value ="22222" /> <dubbo:parameter key ="qos.accept.foreign.ip" value ="false" /> </dubbo:application > <dubbo:registry address ="zookeeper://127.0.0.1:2181" timeout ="5000" /> <dubbo:protocol name ="dubbo" port ="20880" /> <dubbo:service interface ="com.clay.dubbo.service.DemoService" ref ="demoService" /> <bean id ="demoService" class ="com.clay.dubbo.provider.service.DemoServiceImpl" /> </beans >
Dubbo 的 Qos 服务
Dubbo QoS(Quality of Service)服务是 Dubbo 框架中用于提供服务的监控和管理功能的一个机制。 启用 QoS 服务后,默认会占用 22222
端口,用户使用 telnet
命令可以很方便地管理服务,比如查询服务列表、上线服务、下线服务等。 为了避免 QoS 服务发生端口冲突,可以通过 qos.enable
参数关闭 QoS 服务,或者通过 qos.port
参数指定 QoS 服务占用的端口,详细的说明请看 这里 。 服务消费者 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public class ConsumerApplication { public static void main (String[] args) throws IOException { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("consumer.xml" ); DemoService demoService = context.getBean("demoService" , DemoService.class); String result = demoService.sayHello("Dubbo" ); System.out.println("===> " + result); context.start(); System.in.read(); context.close(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns ="http://www.springframework.org/schema/beans" xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo ="http://dubbo.apache.org/schema/dubbo" xsi:schemaLocation =" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd" > <dubbo:application name ="dubbo-consumer-application" > <dubbo:parameter key ="qos.enable" value ="true" /> <dubbo:parameter key ="qos.port" value ="22223" /> <dubbo:parameter key ="qos.accept.foreign.ip" value ="false" /> </dubbo:application > <dubbo:registry address ="zookeeper://127.0.0.1:2181" timeout ="5000" /> <dubbo:reference id ="demoService" interface ="com.clay.dubbo.service.DemoService" /> </beans >
Dubbo 的 Qos 服务
Dubbo QoS(Quality of Service)服务是 Dubbo 框架中用于提供服务的监控和管理功能的一个机制。 启用 QoS 服务后,默认会占用 22222
端口,用户使用 telnet
命令可以很方便地管理服务,比如查询服务列表、上线服务、下线服务等。 为了避免 QoS 服务发生端口冲突,可以通过 qos.enable
参数关闭 QoS 服务,或者通过 qos.port
参数指定 QoS 服务占用的端口,详细的说明请看 这里 。 注解方式使用 Dubbo 提示
本节将在 Spring 项目中,基于注解使用 Dubbo,完整的案例代码可以直接从 GitHub 下载对应章节 dubbo-lesson-02
。
特别注意
Dubbo 从 2.7.7
版本开始提供 @DubboService
和 @DubboReference
注解,目的是为了替代旧版本的 @Service
和 @Reference
注解。
项目结构
引入依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 <properties > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <maven.compiler.source > 1.8</maven.compiler.source > <maven.compiler.target > 1.8</maven.compiler.target > <spring.version > 5.3.31</spring.version > <dubbo.version > 2.7.8</dubbo.version > <netty.version > 4.1.33.Final</netty.version > <curator.version > 3.3.0</curator.version > <commons-lang3.version > 3.4</commons-lang3.version > <slf4j.version > 1.7.36</slf4j.version > <logback.version > 1.2.12</logback.version > </properties > <dependencies > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-core</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-context</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.springframework</groupId > <artifactId > spring-web</artifactId > <version > ${spring.version}</version > </dependency > <dependency > <groupId > org.apache.dubbo</groupId > <artifactId > dubbo</artifactId > <version > ${dubbo.version}</version > </dependency > <dependency > <groupId > io.netty</groupId > <artifactId > netty-all</artifactId > <version > ${netty.version}</version > </dependency > <dependency > <groupId > org.apache.curator</groupId > <artifactId > curator-recipes</artifactId > <version > ${curator.version}</version > </dependency > <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-lang3</artifactId > <version > ${commons-lang3.version}</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-api</artifactId > <version > ${slf4j.version}</version > </dependency > <dependency > <groupId > ch.qos.logback</groupId > <artifactId > logback-classic</artifactId > <version > ${logback.version}</version > </dependency > </dependencies >
日志配置 1 2 3 4 5 6 7 log4j.rootLogger =DEBUG, console log4j.appender.console =org.apache.log4j.ConsoleAppender log4j.appender.console.layout =org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern =%d{ISO8601} %-5p [%t] %c{1} - %m%n
公共接口 1 2 3 4 5 public interface DemoService { String sayHello (String name) ; }
服务提供者 接口实现类,这里的 @DubboService
注解是 Dubbo 提供的。值得一提的是,旧版本的 Dubbo 使用的是 @Service
注解,这里的 @Service
注解由 Dubbo 提供,并不是 Spring 提供的那一个。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 import org.apache.dubbo.config.annotation.DubboService;@DubboService public class DemoServiceImpl implements DemoService { @Override public String sayHello (String name) { return "Hello " + name; } }
服务提供者,使用 @EnableDubbo
注解启用 Dubbo 1 2 3 4 5 6 7 8 9 10 11 12 13 @EnableDubbo(scanBasePackages = "com.clay.dubbo.provider") @PropertySource("classpath:/provider.properties") @ComponentScan("com.clay.dubbo.provider") public class ProviderApplication { public static void main (String[] args) throws IOException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProviderApplication.class); context.start(); System.in.read(); context.close(); } }
核心配置(provider.properties
) 1 2 3 4 5 6 7 dubbo.application.name =dubbo-provider-application dubbo.application.qosEnable =true dubbo.application.qosPort =22222 dubbo.application.qosAcceptForeignIp =false dubbo.registry.address =zookeeper://127.0.0.1:2181 dubbo.protocol.name =dubbo dubbo.protocol.port =20880
Dubbo 的 Qos 服务
Dubbo QoS(Quality of Service)服务是 Dubbo 框架中用于提供服务的监控和管理功能的一个机制。 启用 QoS 服务后,默认会占用 22222
端口,用户使用 telnet
命令可以很方便地管理服务,比如查询服务列表、上线服务、下线服务等。 为了避免 QoS 服务发生端口冲突,可以通过 qos.enable
参数关闭 QoS 服务,或者通过 qos.port
参数指定 QoS 服务占用的端口,详细的说明请看 这里 。 服务消费者 业务测试类,这里的 @DubboReference
注解是 Dubbo 提供的。值得一提的是,旧版本的 Dubbo 使用的是 @Reference
注解。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import org.apache.dubbo.config.annotation.Reference;@Component public class ConsumerAction { @DubboReference private DemoService demoService; public String doSayHello (String name) { return demoService.sayHello(name); } }
服务消费者,使用 @EnableDubbo
注解启用 Dubbo 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @EnableDubbo(scanBasePackages = "com.clay.dubbo.consumer") @PropertySource("classpath:/consumer.properties") @ComponentScan("com.clay.dubbo.consumer") public class ConsumerApplication { public static void main (String[] args) throws IOException { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerApplication.class); ConsumerAction consumerAction = context.getBean(ConsumerAction.class); String result = consumerAction.doSayHello("Dubbo" ); System.out.println("===> " + result); context.start(); System.in.read(); context.close(); } }
核心配置(consumer.properties
) 1 2 3 4 5 dubbo.application.name =dubbo-consumer-application dubbo.application.qosEnable =true dubbo.application.qosPort =22223 dubbo.application.qosAcceptForeignIp =false dubbo.registry.address =zookeeper://127.0.0.1:2181
Dubbo 的 Qos 服务
Dubbo QoS(Quality of Service)服务是 Dubbo 框架中用于提供服务的监控和管理功能的一个机制。 启用 QoS 服务后,默认会占用 22222
端口,用户使用 telnet
命令可以很方便地管理服务,比如查询服务列表、上线服务、下线服务等。 为了避免 QoS 服务发生端口冲突,可以通过 qos.enable
参数关闭 QoS 服务,或者通过 qos.port
参数指定 QoS 服务占用的端口,详细的说明请看 这里 。 原生 API 方式使用 Dubbo 提示
本节将在 Java 项目中,基于原生 API 使用 Dubbo,完整的案例代码可以直接从 GitHub 下载对应章节 dubbo-lesson-03
。
项目结构
引入依赖 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 <properties > <project.build.sourceEncoding > UTF-8</project.build.sourceEncoding > <maven.compiler.source > 1.8</maven.compiler.source > <maven.compiler.target > 1.8</maven.compiler.target > <dubbo.version > 2.7.8</dubbo.version > <netty.version > 4.1.33.Final</netty.version > <curator.version > 3.3.0</curator.version > <commons-lang3.version > 3.4</commons-lang3.version > <slf4j.version > 1.7.36</slf4j.version > <logback.version > 1.2.12</logback.version > </properties > <dependencies > <dependency > <groupId > org.apache.dubbo</groupId > <artifactId > dubbo</artifactId > <version > ${dubbo.version}</version > </dependency > <dependency > <groupId > io.netty</groupId > <artifactId > netty-all</artifactId > <version > ${netty.version}</version > </dependency > <dependency > <groupId > org.apache.curator</groupId > <artifactId > curator-recipes</artifactId > <version > ${curator.version}</version > </dependency > <dependency > <groupId > org.apache.commons</groupId > <artifactId > commons-lang3</artifactId > <version > ${commons-lang3.version}</version > </dependency > <dependency > <groupId > org.slf4j</groupId > <artifactId > slf4j-api</artifactId > <version > ${slf4j.version}</version > </dependency > <dependency > <groupId > ch.qos.logback</groupId > <artifactId > logback-classic</artifactId > <version > ${logback.version}</version > </dependency > </dependencies >
日志配置 1 2 3 4 5 6 7 log4j.rootLogger =DEBUG, console log4j.appender.console =org.apache.log4j.ConsoleAppender log4j.appender.console.layout =org.apache.log4j.PatternLayout log4j.appender.console.layout.ConversionPattern =%d{ISO8601} %-5p [%t] %c{1} - %m%n
公共接口 1 2 3 4 5 public interface DemoService { String sayHello (String name) ; }
服务提供者 1 2 3 4 5 6 7 8 public class DemoServiceImpl implements DemoService { @Override public String sayHello (String name) { return "Hello " + name; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 import org.apache.dubbo.config.ApplicationConfig;import org.apache.dubbo.config.ProtocolConfig;import org.apache.dubbo.config.RegistryConfig;import org.apache.dubbo.config.ServiceConfig;public class ProviderApplication { public static void main (String[] args) throws IOException { DemoService demoService = new DemoServiceImpl(); ApplicationConfig applicationConfig = new ApplicationConfig(); applicationConfig.setName("dubbo-provider-application" ); applicationConfig.setQosEnable(true ); applicationConfig.setQosPort(22222 ); applicationConfig.setQosAcceptForeignIp(false ); RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setProtocol("zookeeper" ); registryConfig.setAddress("127.0.0.1" ); registryConfig.setPort(2181 ); registryConfig.setTimeout(5000 ); ProtocolConfig protocolConfig = new ProtocolConfig(); protocolConfig.setName("dubbo" ); protocolConfig.setPort(20880 ); protocolConfig.setThreads(200 ); ServiceConfig<DemoService> service = new ServiceConfig<>(); service.setApplication(applicationConfig); service.setRegistry(registryConfig); service.setProtocol(protocolConfig); service.setInterface(DemoService.class); service.setRef(demoService); service.setVersion("1.0.0" ); service.export(); System.in.read(); } }
服务消费者 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import org.apache.dubbo.config.ApplicationConfig;import org.apache.dubbo.config.ReferenceConfig;import org.apache.dubbo.config.RegistryConfig;public class ConsumerApplication { public static void main (String[] args) throws IOException { ApplicationConfig applicationConfig = new ApplicationConfig(); applicationConfig.setName("dubbo-consumer-application" ); applicationConfig.setQosEnable(true ); applicationConfig.setQosPort(22223 ); applicationConfig.setQosAcceptForeignIp(false ); RegistryConfig registryConfig = new RegistryConfig(); registryConfig.setProtocol("zookeeper" ); registryConfig.setAddress("127.0.0.1" ); registryConfig.setPort(2181 ); registryConfig.setTimeout(5000 ); ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>(); referenceConfig.setApplication(applicationConfig); referenceConfig.setRegistry(registryConfig); referenceConfig.setInterface(DemoService.class); referenceConfig.setVersion("1.0.0" ); DemoService demoService = referenceConfig.get(); String result = demoService.sayHello("Dubbo" ); System.out.println("===> " + result); System.in.read(); } }
Dubbo 整合使用 SpringBoot 整合 Dubbo