任何一个公司的系统基本都是从最简单的Mvc架构,随着用户量的增加,系统暴露出各种各样的问题,因此,变更系统架构就成为了重中之中的事情,那么,不同架构之间的优点和缺点都有哪些呢?
1.单一应用框架(ORM)
当网站流量很小时,只需一个应用,将所有功能如下单支付等都部署在一起,以减少部署节点和成本。
缺点:单一的系统架构,使得在开发过程中,占用的资源越来越多,而且随着流量的增加越来越难以维护
2.垂直应用框架(MVC)
垂直应用架构解决了单一应用架构所面临的扩容问题,流量能够分散到各个子系统当中,且系统的体积可控,一定程度上降低了开发人员之间协同以及维护的成本,提升了开发效率。
缺点:但是在垂直架构中相同逻辑代码需要不断的复制,不能复用。
3.流动计算架构(SOA)
随着服务化的进一步发展,服务越来越多,服务之间的调用和依赖关系也越来越复杂,诞生了面向服务的架构体系(SOA),也因此衍生出了一系列相应的技术,如对服务提供、服务调用、连接处理、通信协议、序列化方式、服务发现、服务路由、日志输出等行为进行封装的服务框架.
-
单一应用架构
- 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。
- 此时,用于简化增删改查工作量的 数据访问框架(ORM) 是关键。
-
垂直应用架构
- 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。
- 此时,用于加速前端页面开发的 Web框架(MVC) 是关键。
流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。
此时,用于提高机器利用率的 资源调度和治理中心(SOA) 是关键。
Dubbo是什么
Dubbo是:
- 一款分布式服务框架
- 高性能和透明化的RPC远程服务调用方案
-
SOA服务治理方案
每天为2千多个服务提供大于30亿次访问量支持,并被广泛应用于阿里巴巴集团的各成员站点以及别的公司的业务中。
- Provider: 暴露服务的服务提供方。
- Consumer: 调用远程服务的服务消费方。
- Registry: 服务注册与发现的注册中心。
- Monitor: 统计服务的调用次数和调用时间的监控中心。
调用流程
1.服务容器负责启动,加载,运行服务提供者。
2.服务提供者在启动时,向注册中心注册自己提供的服务。
3.服务消费者在启动时,向注册中心订阅自己所需的服务。
4.注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
5.服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
6.服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心
Dubbo注册中心
对于服务提供方,它需要发布服务,而且由于应用系统的复杂性,服务的数量、类型也不断膨胀;
对于服务消费方,它最关心如何获取到它所需要的服务,而面对复杂的应用系统,需要管理大量的服务调用。
而且,对于服务提供方和服务消费方来说,他们还有可能兼具这两种角色,即既需要提供服务,有需要消费服务。
通过将服务统一管理起来,可以有效地优化内部应用对服务发布/使用的流程和管理。服务注册中心可以通过特定协议来完成服务对外的统一。
Dubbo提供的注册中心有如下几种类型可供选择:
- Multicast注册中心
- Zookeeper注册中心
- Redis注册中心
- Simple注册中心
Dubbo优缺点
优点:
透明化的远程方法调用
- 像调用本地方法一样调用远程方法;只需简单配置,没有任何API侵入。
软负载均衡及容错机制
可在内网替代nginx lvs等硬件负载均衡器。
服务注册中心自动注册 & 配置管理 - 不需要写死服务提供者地址,注册中心基于接口名自动查询提供者ip。
使用类似zookeeper等分布式协调服务作为服务注册中心,可以将绝大部分项目配置移入zookeeper集群。
服务接口监控与治理 - Dubbo-admin与Dubbo-monitor提供了完善的服务接口管理与监控功能,针对不同应用的不同接口,可以进行 多版本,多协议,多注册中心管理。
缺点:
只支持JAVA语言
Dubbo入门Hello word
了解了Dubbo以后,自然要搭建一个简单的Demo实现。本文采用Dubbo与Zookeeper、Spring框架的整合。
主要是以下几个步骤:
- 创建dubbo-api
- 创建dubbo-provider(服务提供者)
-
创建dubbo-consumer(服务消费者)
项目搭建
1.搭建dubbo-api
创建dubbo-api的MAVEN项目(有独立的pom.xml,用来打包供提供者消费者使用)。
在项目中定义服务接口:该接口需单独打包,在服务提供方和消费方共享。
dubbo-api的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">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>dubbo-hello</artifactId>
<groupId>hrabbit-dubbo-hello</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<packaging>jar</packaging>
<artifactId>dubbo-hello-api</artifactId>
</project>
创建公共接口api
package www.hrabbit.cn.api;
/**
* dubbo api
* @Auther: hrabbit
* @Date: 2018-03-12 上午11:23
* @Description:
*/
public interface HelloService {
/**
* hello 接口
* @param hello
* @return
*/
public String sayHello(String hello);
}
2.搭建dubbo-provider
创建dubbo-provider的MAVEN项目,将包打包成jar包,因为需要独立部署
dubbo-provider的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>dubbo-hello</artifactId>
<groupId>hrabbit-dubbo-hello</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-hello-provider</artifactId>
<properties>
<!--指定编码方式-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 引入api-->
<dependency>
<groupId>hrabbit-dubbo-hello</groupId>
<artifactId>dubbo-hello-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- spring begin -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- spring end -->
<!-- dubbo begin -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
<!-- dubbo end -->
<!-- 注册中心zookeeper begin -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.6</version>
</dependency>
<!-- 注册中心zookeeper end -->
<!-- log begin -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
<exclusion>
<artifactId>jms</artifactId>
<groupId>javax.jms</groupId>
</exclusion>
<exclusion>
<artifactId>mail</artifactId>
<groupId>javax.mail</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- log end -->
<!-- other begin -->
<dependency>
<groupId>org.jboss.netty</groupId>
<artifactId>netty</artifactId>
<version>3.2.0.Final</version>
</dependency>
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.8</version>
</dependency>
</dependencies>
</project>
在resources目录下配置application-provider.xml
<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd ">
<dubbo:application name="dubbo-demo" />
<!-- zookeeper注册中心 -->
<dubbo:registry address="zookeeper://127.0.0.1:2181" />
<dubbo:protocol name="dubbo" port="20880" />
<!-- 和本地bean一样实现服务 -->
<bean id="demoService" class="www.hrabbit.cn.provider.HelloServiceImpl" />
<!-- 向注册中心注册暴漏服务地址,注册服务 -->
<dubbo:service interface="www.hrabbit.cn.api.HelloService"
ref="demoService" executes="10" />
</beans>
添加接口实现类,提供服务,添加HelloServiceImpl.java
package www.hrabbit.cn.provider;
import www.hrabbit.cn.api.HelloService;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* 服务提供者
* @Auther: hrabbit
* @Date: 2018-03-12 上午11:34
* @Description:
*/
public class HelloServiceImpl implements HelloService {
/**
* 实现say hello接口
* @param hello
* @return
*/
public String sayHello(String hello) {
return "The time:"+ new SimpleDateFormat("yyyy-HH-dd").format(new Date())+";To say:"+hello;
}
}
启动远程服务:
创建Provider.java,读取配置文件,启动远程服务
package www.hrabbit.cn.provider;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
/**
* 服务提供者
* @Auther: hrabbit
* @Date: 2018-03-12 下午2:15
* @Description:
*/
public class Provider {
public static void main(String[] args) throws IOException {
//获取配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[] { "application-provider.xml" });
context.start();
System.in.read();
}
}
3.搭建dubbo-provider
创建dubbo-provider的MAVEN项目,将包打包成jar包,因为需要独立部署
dubbo-consumer的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>dubbo-hello</artifactId>
<groupId>hrabbit-dubbo-hello</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dubbo-hello-consumer</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--api-->
<dependency>
<groupId>hrabbit-dubbo-hello</groupId>
<artifactId>dubbo-hello-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>hrabbit-dubbo-hello</groupId>
<artifactId>dubbo-hello-provider</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- spring begin -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.1.6.RELEASE</version>
</dependency>
<!-- spring end -->
<!-- dubbo begin -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.5.3</version>
</dependency>
<!-- dubbo end -->
<!-- 注册中心zookeeper begin -->
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.3.6</version>
</dependency>
<!-- 注册中心zookeeper end -->
<!-- log begin -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.15</version>
<exclusions>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
<exclusion>
<artifactId>jms</artifactId>
<groupId>javax.jms</groupId>
</exclusion>
<exclusion>
<artifactId>mail</artifactId>
<groupId>javax.mail</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- log end -->
<!-- other begin -->
<dependency>
<groupId>com.101tec</groupId>
<artifactId>zkclient</artifactId>
<version>0.8</version>
</dependency>
<!-- other end -->
</dependencies>
</project>
在resources目录下配置application-consumer.xml
<?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://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd ">
<!-- consumer's application name, used for tracing dependency relationship (not a matching criterion),
don't set it same as provider -->
<dubbo:application name="dubbo-demo"/>
<!-- use multicast registry center to discover service -->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<!-- generate proxy for the remote service, then demoService can be used in the same way as the
local regular interface -->
<dubbo:reference id="demoService" check="false" interface="www.hrabbit.cn.api.HelloService"/>
</beans>
启动远程服务:
创建HelloConsumer.java,读取配置文件,根据服务名称,消费服务的api
package www.hrabbit.cn.consumer;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import www.hrabbit.cn.api.HelloService;
/**
* 服务消费者
* @Auther: hrabbit
* @Date: 2018-03-12 下午2:50
* @Description:
*/
public class HelloConsumer {
public static void main(String[] args) {
//读取配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext( new String[] { "application-consumer.xml" });
context.start();
//获取bean对象
HelloService service = (HelloService) context.getBean("demoService");
System.out.println(service.sayHello("hello world"));
context.close();
}
}
到这一步,我们的项目创建成功了,我们首先需要启动服务提供者,然后启动服务消费者,这样就会在控制台打印出hello word!证明我们dubbo-hello的入门案例就成功搭建了!