目录
一、系统架构的演变
1.1 单体架构
在企业发展的初期,一般公司的网站流量都比较小,只需要一个应用,将所有的功能代码打包成一个服务,部署到服务器上就能支撑公司的业务。这样也能够减少开发、部署和维护的成本。
比如,大家都很熟悉的电商系统,里面涉及的业务主要有:用户管理、商品管理、订单管理、支付管理、库存管理、物流管理等等模块,初期我们会将所有模块写到一个Web项目中,然后统一部署到一台tomcat服务器上。
单体架构有何缺点:
- 代码耦合:模块的边界模糊、依赖关系不清晰,整个项目非常复杂,每次修改代码都心惊胆战
- 迭代困难:每次功能的变更或bug的修复都会导致重新部署整个应用,随着代码的增多,构建、测试和部署的时间也会增加
- 扩展受限:单体应用只能作为一个整体进行扩展,无法根据业务模块的需要进行伸缩
- 技术债务:随着时间推移、需求变更和人员更迭,会逐渐形成应用程序的技术债务,并且越积越多不坏不修
- 阻碍创新:单体应用往往使用统一的技术平台或方案解决所有的问题,要想引入新技术平台会非常困难
乍一看问题还是挺多的,单体架构天生做不了大项目的
1.2 分布式架构
随着企业业务的不断发展,发现单节点的单体应用不足以支撑业务的发展,于是企业会将单体应用部署多份,分别放在不同的服务器上。但是,此时会发现不是所有的模块都会有比较大的访问量。如果想针对项目中的某些模块进行优化和性能提升,此时对于单体应用来说,是做不到的。于是乎,分布式架构诞生了。
分布式架构,就是将原来一个项目应用进行拆分,将其拆分为互不想干的几个应用,以此来提升系统的整体性能。
这里,我们同样以电商系统为例,在分布式架构下,我们可以将整个电商项目拆分为:电商交易系统、后台管理系统、CMS管理系统等。
分布式架构优点:
- 不同的团队负责不同的子项目
- 可以灵活的进行分布式部署
- 可以为某一模块单独加集群
分布式架构缺点:
- 各系统难免存在重叠的业务(如订单服务、物流、推广都需要调用用户服务)
1.3 soa架构
我们将系统演变为分布式架构之后,当业务越来越多,重复编写的业务代码就会越来越多。此时,我们需要将重复的代码抽象出来,形成统一的服务供其他系统或者业务模块来进行调用。此时,系统就会演变为SOA架构。
在SOA架构中,我们会将系统整体拆分为服务层和表现层。服务层封装了具体的业务逻辑供表现层调用,表现层则负责处理与页面的交互操作。
当部署的服务越来越多,就会出现服务集群地址硬编码的问题,此时,我们就需要增加一个注册中心来解决各个服务之间的注册与发现。
存在的问题:
-
服务提供方与调用方接口耦合度较高(如果提供方的服务器出现宕机则会导致多个模块无法使用)
-
抽取服务的粒度较大
1.4 微服务
随着业务的发展,我们在SOA架构的基础上进一步扩展,将其彻底拆分为一个个小的可以独立部署的微服务。
微服务架构特征:
-
隔离性强:服务调用的隔离、容错、避免出现级联问题
-
面向服务:微服务对外暴露Restful等轻量协议的接口
-
单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发
-
自治:独立打包、部署和升级,小团队的交付周期将缩短,运维成本也将大幅度下降
二、dubbox框架
2.1 dubbox简介
Dubbox是一个分布式服务框架,其前身是阿里巴巴开源项目Dubbo,被国内电商及互联网项目中使用,后期阿里巴巴停止了该项目的维护,当当网便在Dubbo基础上进行优化,并继续维护,为了与原有的Dubbo区分,故将其命名为Dubbox。
Dubbox致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案。其实Dubbox就是个远程服务调用的分布式框架。
节点角色说明:
Provider: 暴露服务的服务提供方。
Container: 服务运行容器。
Registry: 服务注册与发现的注册中心。
Consumer: 调用远程服务的服务消费方。
Monitor: 统计服务的调用次调和调用时间的监控中心。
三、zookeeper注册中心
3.1 zookeeper介绍
Zookeeper是Apacahe Hadoop的子项目,可以为分布式应用程序协调服务,适合作为Dubbo服务的注册中心,负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互。
3.2 zookeeper的安装和启动
1、安装jdk
2、上传并解压缩zookeeper压缩包
tar -zxvf zookeeper-3.4.11.tar.gz -C /usr/local
3、将conf文件夹下zoo_sample.cfg复制一份,改名为zoo.cfg
cd /usr/local/zookeeper-3.4.11/conf
cp zoo_sample.cfg zoo.cfg
4、修改配置dataDir属性,指定一个真实目录
vim zoo.cfg:
dataDir=/usr/local/zookeeper-3.4.11/data
5、创建目录
cd /usr/local/zookeeper-3.4.11
mkdir data
6、进入 bin 目录,启动服务输入命令
./zkServer.sh start
7、关闭服务输入命令
./zkServer.sh stop
8、查看服务状态
./zkServer.sh status
四、入门案例
4.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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bjpowernode</groupId>
<artifactId>dubbox_parent</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>dubbox_interface</module>
<module>dubbox_provider</module>
<module>dubbox_consumer</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.1.0</version>
</dependency>
<!-- 由于使⽤了zookeeper作为注册中⼼,则需要加⼊zookeeper的客户端jar包: -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.10</version>
</dependency>
</dependencies>
</project>
4.2 创建消费者consumer
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>dubbox_parent</artifactId>
<groupId>com.bjpowernode</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbox_consumer</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>dubbox_interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
controller
package com.bjpowernode.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.bjpowernode.service.HelloService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@Reference//dubbo提供的注解,注入接口
private HelloService helloService;
@RequestMapping("/hello")
public String hello(){
return helloService.hello();
}
}
启动类
package com.bjpowernode;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DubboxConsumerApp {
public static void main(String[] args) {
SpringApplication.run(DubboxConsumerApp.class,args);
}
}
配置文件application.yml(核心)
server: port: 8080 dubbo: registry: #zookeeper地址 address: zookeeper://192.168.57.129:2181 #当前服务的名字 application: name: dubbo-consumer #协议,dubbo支持的协议有dubbo、RMT、http、WebService protocol: name: dubbo
4.3 创建接口interface
此工程只写接口,其他服务可以通过依赖引入
package com.bjpowernode.service;
public interface HelloService {
String hello();
}
4.5 创建提供者provider
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>dubbox_parent</artifactId>
<groupId>com.bjpowernode</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbox_provider</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>dubbox_interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
配置文件application.yml
server: port: 8081 #端口不能和其他端口冲突 dubbo: registry: #zookeeper地址 address: zookeeper://192.168.57.129:2181 #当前服务的名字 application: name: dubbo-service #协议,dubbo支持的协议有dubbo、RMT、http、WebService protocol: name: dubbo
启动类上要加入@EnableDubbo注解用来扫描@Service和@Reference注解。
package com.bjpowernode;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableDubbo//用来扫描@Service和@Reference注解。
public class DubboxProviderApp {
public static void main(String[] args) {
SpringApplication.run(DubboxProviderApp.class,args);
}
}
创建接口的实现类
注意这里的@Service注解要引入import com.alibaba.dubbo.config.annotation.Service,不要引错了
package com.bjpowernode.service;
import com.alibaba.dubbo.config.annotation.Service;
@Service
public class HelloServiceImpl implements HelloService{
@Override
public String hello() {
return "hello word...";
}
}
4.6 测试
注意要先启动provider提供者然后再启动消费者