提示:要直接看搭建例子的可以跳到 三
一.项目架构的发展
传统的mvc架构项目将整个系统功能实现全部写在一个项目中,部署在一个机器上,随着用户量的增涨,单个项目服务器无法承受暴增的用户请求时需要增加服务器数量,并通过负载均衡集群将项目部署到多个服务器上,提高项目可处理的用户请求总数。
当mvc架构项目中的某个或某几个模块的用户请求量较大,其他模块用户请求量较小,此时负载均衡集群依然是每个服务器部署一个完整的项目,实际需要进行负载均衡的仅是用户请求量较大的几个模块,此处则可采用分布式将系统功能模块服务化。
在项目过于庞大,部署单项目无法满足需求时,需要将项目的不同功能模块拆分成单独的服务项目部署到不同的服务器上(也就是分布式)。
在分布式中,各个服务项目之间要进行相互调用,需要在知道地址的情况下通过网络进行访问。此时需要一个能让所有服务都能得知其他服务地址的中间人,由此产生了服务注册中心,服务项目需要告诉服务注册中心它是干嘛的,也就是进行服务注册,
当其他项目要调用特定服务时可以到服务注册中心查找服务项目的地址,获取到服务项目地址后即可通过网络地址自行调用该服务项目,这整个过程涉及的结构也就是rpc架构的内容。
rpc架构:
包含服务提供者、服务消费者、服务注册中心;
服务注册中心:在服务提供者进行服务注册时保存服务提供者信息,在服务消费者进行服务发现时返回服务提供者地址;
服务提供者provider:在服务注册中心进行服务注册,等待服务消费者调用;
服务消费者consumer:在服务注册中心进行服务发现,在得到服务注册中心返回的服务提供者地址后进行服务调用;
rpc架构缺点:当项目拆分服务过多时无法得知服务是否正在被谁使用;
soa服务化架构:在rpc架构的基础上加了服务治理系统;
二.Zookeeper与Dubbo分别是什么?各自在项目中充当什么角色?
Zookeeper是什么:
Apache ZooKeeper是由集群(节点组)使用的一种服务,用于在自身之间协调,并通过稳健的同步技术维护共享数据。ZooKeeper本身是一个分布式应用程序,为写入分布式应用程序提供服务。
zookeeper充当的角色:
在上述rpc架构中zookeeper就是一个服务注册中心,所有的服务都在zookeeper中进行登记(服务注册),当某个服务要调用其他服务时,问zookeeper要该服务的网络地址(服务发现)。
dubbo是什么:
Dubbo是一款高性能、轻量级的开源Java RPC框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
dubbo充当的角色:
rpc架构的系统中所有服务项目都需要进行服务注册(告诉服务注册中心我是谁)与服务发现(告诉服务注册中心我要找谁),服务提供者和服务消费者(也就是服务本身)可使用dubbo来负责服务注册与服务发现。
dubbo对rpc架构缺点的处理:
Dubbo提供了dubbo-admin服务治理系统,在搭建dubbo+zookeeper后可运行dubbo-admin系统进行服务管理,也就从rpc架构变成了soa服务化架构。
三.搭建dubbo+zookeeper小例子
在正式搭建前可以先安装并启动zookeeper(略),随后安装dubbo-admin,下载dubbo-admin.war,改名ROOT.war,放到tomcat中,启动后可修改其中的dubbo.properties,将地址和账号密码修改成你安装的zookeeper的,随后重启项目
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.admin.root.password=root
dubbo.admin.guest.password=guest
然后可以访问localhost:8080(修改为ROOT.war就是为了能localhost:8080直接访问项目),登录dubbo-admin后可以进去逛逛
在搭建到步骤3或步骤4时可以启动项目,然后到dubbo-admin服务管理系统中查看消费者和提供者是否有对应的数据,可以此为依据,判断服务是否注册成功。
1.创建maven项目,并在项目中创建三个子项目,service项目用于编写公共服务接口,dubboProvider去实现service中的接口,dubboConsumer用于调用公共服务接口在dubboProvider中的实现
2.在service项目中新增一个接口:
package com.lwl.service; public interface DemoService { String sayHello(String name); }
3.dubboProvider中的操作:
3-1)在dubboProvider项目的pom.xml中加入依赖
<dependency> <groupId>com.lwlgroupId> <artifactId>serviceartifactId> <version>1.0version> dependency> <dependency> <groupId>com.alibabagroupId> <artifactId>dubboartifactId> <version>2.5.10version> <exclusions> <exclusion> <groupId>org.springframeworkgroupId> <artifactId>spring-webartifactId> exclusion> <exclusion> <groupId>org.springframeworkgroupId> <artifactId>spring-contextartifactId> exclusion> <exclusion> <groupId>org.springframeworkgroupId> <artifactId>spring-beansartifactId> exclusion> <exclusion> <groupId>org.jboss.nettygroupId> <artifactId>nettyartifactId> exclusion> exclusions> dependency> <dependency> <groupId>com.101tecgroupId> <artifactId>zkclientartifactId> <version>0.11version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-webartifactId> <version>5.1.8.RELEASEversion> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-contextartifactId> <version>5.1.8.RELEASEversion> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-beansartifactId> <version>5.1.8.RELEASEversion> dependency>
3-2)创建DemoServiceImpl 类,实现公共服务接口
package com.lwl.service.impl; import com.lwl.service.DemoService; public class DemoServiceImpl implements DemoService { @Override public String sayHello(String name) { return "Hello " + name; } }
3-3)在web.xml中配置启动spring
xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <context-param> <param-name>contextConfigLocationparam-name> <param-value>classpath:applicationContext.xmlparam-value> context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListenerlistener-class> listener> web-app>
3-4)在applicationContext.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:context="http://www.springframework.org/schema/context" xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"> <context:component-scan base-package="com.lwl.service"/> <bean id="demoService" class="com.lwl.service.impl.DemoServiceImpl"/>
<dubbo:application name="dubbo-provider"/> <dubbo:registry address="zookeeper://127.0.0.1:2181" check="false" subscribe="false" register=""/> <dubbo:protocol name="dubbo" port="20880"/> <dubbo:service interface="com.lwl.service.DemoService" ref="demoService" timeout="600000"/> beans>
4.在dubboConsumer项目中的操作:
4-1)在dubboConsumer项目的pom.xml文件添加依赖:
<dependency> <groupId>com.lwlgroupId> <artifactId>serviceartifactId> <version>1.0version> dependency> <dependency> <groupId>com.alibabagroupId> <artifactId>dubboartifactId> <version>2.5.10version> <exclusions> <exclusion> <groupId>org.springframeworkgroupId> <artifactId>spring-webartifactId> exclusion> <exclusion> <groupId>org.springframeworkgroupId> <artifactId>spring-contextartifactId> exclusion> <exclusion> <groupId>org.springframeworkgroupId> <artifactId>spring-beansartifactId> exclusion> <exclusion> <groupId>org.jboss.nettygroupId> <artifactId>nettyartifactId> exclusion> exclusions> dependency> <dependency> <groupId>com.101tecgroupId> <artifactId>zkclientartifactId> <version>0.11version> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-webmvcartifactId> <version>5.1.8.RELEASEversion>
dependency>
4-2)在web.xml中启动springmvc
xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <servlet> <servlet-name>spring-mvcservlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class> <init-param> <param-name>contextConfigLocationparam-name> <param-value>classpath:spring-mvc.xmlparam-value> init-param> <load-on-startup>1load-on-startup> servlet> <servlet-mapping> <servlet-name>spring-mvcservlet-name> <url-pattern>/url-pattern> servlet-mapping> <welcome-file-list> <welcome-file>index.jspwelcome-file> welcome-file-list> web-app>
4-3)在spring-mvc.xml中
xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" 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-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> <context:component-scan base-package="com.lwl.controller"/> <context:annotation-config/> <dubbo:application name="dubbo-consumer"/> <dubbo:registry address="zookeeper://127.0.0.1:2181" check="false"/> <dubbo:reference interface="com.lwl.service.DemoService" id="demoService"/> <mvc:annotation-driven/> beans>
4-4)创建controller:
package com.lwl.controller; import com.lwl.service.DemoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @RestController public class DemoController { // @Autowired // 默认按byType自动注入,当找不到对应类型的bean时才按byName自动注入,都找不到时抛出异常 // 默认情况下必须要求依赖对象必须存在,如果要允许null值可使用@Autowired(required=false) // @Resource // 默认按byName自动注入,找不到时抛出异常 @Resource//或使用@Autowired(required = false) private DemoService demoService; @GetMapping("/{name}") public String get(@PathVariable String name) { return demoService.sayHello(name); } }
5.先启动dubboProvider项目,随后启动dubboConsumer项目,启动后访问http://localhost:8080/dubboConsumer/** 返回 Hello ** 则配置成功