<<分布式原理与范型>>
分布式系统是若干独立系统的集合,但是用户使用起来像是在使用一套系统
为什么需要分布式系统?
规模的扩大和业务的复杂,单台计算机扛不住双十一那样的流量,三个臭皮匠抵一个诸葛亮
1. 单一架构
当网站流量很小的时候,我们将所有的应用(业务)放到一台服务器上,打包运行
公司管理系统/超市收银系统
优点:开发简单,部署简单
缺点:扩展不容易(怎么处理日益增长的流量),谁都改一个,维护不容易,性能提升难
2. 垂直应用架构
将大应用拆分成为小应用(一般按照业务拆分),根据不同的访问频率决定各自业务部署的服务器数量
优点:扩展容易
缺点:页面一改,可能造成整个项目重新部署,业务和界面没有分离开,随着业务种类增加,怎么解决业务之间的互相调用问题,订单服务器和用户服务器交互效率的问题
3. 分布式架构(基于RPC:远程过程调用)
将业务拆分后,用某种方式实现各个业务模块的远程调用和复用,这时一个好的RPC框架就决定了你的分布式架构的性能,怎么调用,何时调用,服务器挂了怎么办......我们需要一个框架来帮我们解决这个问题(当然大大神可以自己写一个,但是应对大流量的集大成者莫过于中国的阿里巴巴公司,顶住了淘宝双十一的流量,反观12306和研招网,甚至一些学校内部的选课系统,对于大流量时只有两个字--宕机)
这时,我们本套课程的主人公就出现了(Dubbo),Dubbo是一个高性能的RPC框架,解决了分布式中的调用问题
优点:解决了分布式系统中互相调用的问题
缺点:假设有100台服务器,50台用户业务服务器,50台订单业务服务器,但是在上线后发现用户服务器使用率很小,但是订单服务器压力很大,最佳配比应该是1:4,这时候就要求我们还有一个统一管理的调度中心
4.流动计算架构
基于第3点中提到的资源浪费问题,我们需要一个能够实时根据调度情况来分配算力的架构,这就是流动计算架构
5. 微服务解决什么问题
微服务要解决什么问题 (高可用>一直可以用[创建副本],高并发,高性能)
造成一切的原因:网络是不可靠的
客户端如何访问这么多的服务?
用户不可能要用什么服务就访问该服务地址,这样做是低效的,我们应该给用户提供一个统一入口
服务聚合,API网关
服务与服务之间怎么通信
同步通信
– HTTP(Apache Http Client)
– RPC(Dubbo 只支持JAVA,别的有Apache Thrift,gRPC)
异步通信
– 消息队列 kafka RabbitMQ RocketMQ
这么多服务如何管理?
服务治理>服务的注册与发现
– 基于客户端的服务注册与发现
Apache Zookeeper
– 基于服务端的服务注册与发现
NetFlix Eureka
服务挂了(宕机)怎么办
– 重试机制
– 服务熔断
– 服务降级
– 服务限流
1. 什么是SOA
以下内容摘自百度百科
面向服务的架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)进行拆分,并通过这些服务之间定义良好的接口和契约联系起来。接口是采用中立的方式进行定义的,它应该独立于实现服务的硬件平台、操作系统和编程语言。这使得构建在各种各样的系统中的服务可以以一种统一和通用的方式进行交互。
SOA类似于OOP,只是一种思想,既然是思想,那么就有落地的实现,Dubbo就是其中的一个
2. SOA和微服务区别
其实没有很大的区别,微服务也是一种思想,是SOA的延伸和升华,在本质上并没有什么大的区别
微服务是在SOA基础上加上了组件化的思想,微服务架构强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。
3. SpringCloud 和 Dubbo区别和对比
如果一个人问"SpringCloud 和 Dubbo"哪个好,说明这个人一定是个小白
首先SpringCloud是为了解决在分布式开发中可能遇到的一揽子问题
而Dubbo是一个RPC框架,只解决远程调用的问题
他们没有好不好的问题,记住一句话 技术没有好坏,只有适合不适合
甚至本文中学习的一些技术,在我们未来开发中会发现使用了这个技术反而让开发维护变得复杂,但是性能没有什么大的提升
这是因为我之前所说的:技术没有好坏,只有适合不适合
而怎么去选择一个合适的技术栈是一个架构师需要去权衡的问题
Oracle和MySQL哪个好?类似这样的问题是没有答案的,这个取决于你的团队对该数据库语言的熟悉程度,以及应用的具体场景,还有预算[手动滑稽脸].我不会告诉你FaceBook现在还在用Mysql+Tomcat
SpringCloud 调用是HTTP方式,而Dubbo是基于RPC协议(本质上就是建立了一个Socket连接,Java基础就有讲,感兴趣可以百度)
4. 再谈RPC
RPC是一种技术思想,而不是具体的落地实现,它的落地实现有很多,但是其中用的最多的就是我们的Dubbo框架.
RPC是远程过程调用(Remote Procedure Call)的缩写形式。SAP系统RPC调用的原理其实很简单,有一些类似于三层构架的C/S系统,第三方的客户程序通过接口调用SAP内部的标准或自定义函数,获得函数返回的数据进行处理后显示或打印。
其实你远程使用别人家的打印机打印一份资料也算RPC,你妈叫你买菜也算RPC
假设有A,B两台服务器,当A想用B上面的一个方法的时候,就会和B建立一个连接,并且告诉B我要调用的方法和参数,这时候B就会将计算好的结果通过连接发给A,结束本次调用(这时候需要思考,每次调用都需要建立连接?这样效率会不会变低?这就是编程思想)
5. 搞定Dubbo
1. 为什么Dubbo说自己性能高
高性能要从底层的原理说起,既然是一个RPC框架,主要干的就是远程过程(方法)调用
提升性能就要从最关键,最耗时的两个方面入手
序列化
网络通信
序列化
而我们学习Java网络开发的时候知道,本地的对象要在网络上传输,必须要实现Serializable接口,也就是必须序列化
我们序列化的方案很多
xml
json
二进制流
其中效率最高的就是二进制流(因为计算机就是二进制的)
Dubbo采用的就是效率最高的二进制
网络通信
不同于HTTP需要进行7步走(三次握手和四次挥手),Dubbo采用Socket通信机制,一步到位,提升了通信效率,并且可以建立长连接,不用反复连接,直接传输数据
2. 别的RPC框架
gRPC
Thrift
HSF
...
3. dubbo的前世今生
dubbo之前一直都作为Alibaba公司内部使用的框架
2011年,dubbo被托管到了GitHub上(开源)
2014年11月发布2.4.11版本后宣布停止更新
此后一段时间很多公司开源了自己基于Dubbo的变种版本(例如当当网的Dubbo X,网易考拉的Dubbo K)
2017年SpringCloud横空出世,Dubbo感觉到压力后连续更新了几个版本
2018年1月,阿里公司联合当当网将Dubbo和Dubbo X合并,发布了2.6版本
2018年除夕夜阿里将Dubbo贡献给了Apache基金会
2018除夕夜至今,Apache维护和更新Dubbo
4. Dubbo强大在哪儿
https://dubbo.apache.org/zh-cn/
以下内容摘自官网
面向接口代理的高性能RPC调用
提供高性能的基于代理的远程调用能力,服务以接口为粒度,为开发者屏蔽远程调用底层细节。
智能负载均衡
内置多种负载均衡策略,智能感知下游节点健康状况,显著减少调用延迟,提高系统吞吐量。
服务自动注册与发现
支持多种注册中心服务,服务实例上下线实时感知。
高度可扩展能力
遵循微内核+插件的设计原则,所有核心能力如Protocol、Transport、Serialization被设计为扩展点,平等对待内置实现和第三方实现。
运行期流量调度
内置条件、脚本等路由策略,通过配置不同的路由规则,轻松实现灰度发布,同机房优先等功能。
可视化的服务治理与运维
提供丰富服务治理、运维工具:随时查询服务元数据、服务健康状态及调用统计,实时下发路由策略、调整配置参数。
他都吹完了,我就不商业互吹了
但是dubbo并不是一套微服务框架,但是它励志成为微服务的一站式解决方案(不同于别的框架只做RPC)
5. 什么是注册中心
假如我们有100台A服务器和100台B服务器,其中一台A想要调用B,这时候A怎么知道要调用哪一台B(总不可能每台A上都存储所有B的信息吧?)
这时候,我们就需要类似于婚介所的角色,这个地方存储了所有的信息(包含A和B),小伙找小姑娘可以随时问婚介所,反之亦然
实际注册中心就能根据负载策略来分配调用哪一台服务器
6. 什么是运行期流量调度(灰度发布)
在新版本(一般是内测版或者公测版上线后),我们可以先让其中的20台服务器先用新的服务,确认无误后再让剩下的80台服务器使用新的服务,保证出现bug的时候损失最小(facebook经常这样来发布新应用)
7. 服务提供者/消费者
远程调用过程必然有服务提供者和消费者,比如订单服务器提供订单服务,用户服务器使用订单服务,其中订单服务器是提供者,用户服务器是消费者.反之亦然.
所以在RPC中没有绝对的消费者和提供者,任何服务都能同时兼备消费者和提供者两个身份,并且绝大多数时候如此
8. 通信模型
通信模型都有什么?
BIO 同步阻塞
NIO 同步非阻塞(Dubbo使用的Netty框架就是使用的这一种通信方式,而Netty 作为一款高性能的通信框架,广泛应用于游戏服务器和物联网服务器)
AIO 异步非阻塞
9.组件角色
Dubbo中的5大组件(角色)
Provider 提供者
Consumer 消费者
Registry 服务发现与注册中心
Monitor 监控中心
Container 服务运行容器
1. 注册中心种类
Dubbo支持的注册中心有很多
Simple
Nacos
Multicast
Zookeeper
其中Dubbo官方推荐使用 Zookeeper作为注册中心
2. 注册中心搭建
参考dubbo.docx里关于Linux下搭建(不是最好的搭建方式,建议使用Docker)
Windows下的安装包解压(我已经解压并放在了E:zookeeper-3.4.11)
进入bin目录
运行zkServer.cmd
到这里我们的Zookeeper服务就启动了
启动bin目录下的zkCli.cmd
运行命令
获取根目录下的数据
get /
获取所有节点(我获取到了两个节点)
ls /
创建节点
create -e /shouwang 123456
ls /
到这里就搭建完成了,但是Zookeeper的功能远不止于此
我们只是用它作为注册中心
Zookeeper 是 Apacahe Hadoop 的子项目,是一个树型的目录服务,支持变更推送,适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,并推荐使用
控制台为我们提供了可视化界面来监控我们的服务运行情况,但是这个在实际生产环境中不一定能使用到,这里我们搭建的目的是为了在开发和学习环境中能更好的监控我们的服务
你可以在GitHub上搜索Dubbo-ops
也可以使用我已经下载好的监控中心
我的已经解压到(E:/incubator-dubbo-ops-master)
进入dubbo-admin目录,会发现一个maven工程pom
<?xmlversion="1.0" encoding="UTF-8"?>
<projectxmlns="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.alibaba</groupId>
<artifactId>dubbo-admin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>dubbo-admin</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
<relativePath/><!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>velocity-spring-boot-starter</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.7</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.46</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
在2.6之前监控中心都是以war包的形式部署(没错,它是作为一个单独项目存在的)
在2.6之后都是jar包的形式部署(自带tomcat)
我们开始打包项目
如果没有配置maven环境变量请参考这篇教程
http://www.cnntt.com/archives/780
cmd进入dubbo-admin目录
首先清空下包
mvn clean package
等待...然后会出现以下提示
BUILD SUCCESS
进入target文件夹,找到我们已经打好的jar包
(关于mvn是怎么打包的可以自己百度,package命令同样可以打包,IDEA同样也可以打包,类似于npm它会根据pom来打包)
得到dubbo-admin-0.0.1-SNAPSHOT.jar(以后可以跳过以上步骤直接使用我打好的jar包)
运行jar
java -jar dubbo-admin-0.0.1-SNAPSHOT.jar
如果报错是因为我们的电脑还没有启动zkServer
我们得到以下提示
Tomcat started on port(s): 7001
我们访问7001即可进入管理控制台
帐号密码都为root
这样我们的环境就搭建完成了
场景假设:
现在我们有两个服务器
订单服务器(独立数据库)
用户服务器(独立数据库)
现在订单服务器要创建一个订单,这时候需要向用户服务器索要用户信息(用户姓名,收货地址等)
在本例中,用户服务器是提供者,订单服务器是消费者
首先打开IDEA,然后创建一个空项目(单项目多module的模式,便于开发)
然后在空项目里面创建user-service module
创建方式同SpringBoot
创建时勾选所有DevTools
为了简化开发,我们的User实体类设计如下
@Data
publicclassUser {
privateInteger id;
privateString name;
privateString addr;
}
设计一个Service接口,用于返回用户信息
publicinterfaceUserService {
/*根据id查询用户信息*/
publicUser getUser(Integer id);
}
实现接口,这里没有连接数据库,我们直接构建一个User
publicclassUserServiceImpl implements UserService {
@Override
publicUser getUser(Integer id) {
User user = new User();
user.setId(1);
user.setName("老覃");
user.setAddr("大连");
returnuser;
}
}
创建方式同上
新建一个创建订单服务(只有一个userId参数)
publicinterfaceOrderService {
/*创建订单*/
publicvoid createOrder(Integer userId);
}
实现方法
publicclassOrderServiceImpl implements OrderService {
@Override
publicvoid createOrder(Integer userId) {
/*查询用户信息*/
}
}
到这里我们就需要进行远程调用了,怎么远程调用?不可能把接口和实现全部拷贝过来,这个就不叫远程调用了,这个叫拷贝代码
所以我们只用把接口拷贝过来,告诉我们有这个方法,具体实现的细节被屏蔽,这个才是分布式开发
首先我们要把pojo和接口(不包含实现类)拷贝到我们的Order项目中
接下来改造我们上面的订单实现方法
publicclassOrderServiceImpl implements OrderService {
UserService userService;
@Override
publicvoid createOrder(Integer userId) {
/*查询用户信息*/
Logger logger = LoggerFactory.getLogger(getClass());
logger.info(userService.getUser(1)+"");
}
}
本次调用必然是失败的
原因有二
方法的实现不在我们的项目中(Order)
即使成功,难道每个调用他的项目都需要拷贝接口和pojo吗
对于以上两个问题,有对应的两个解决方案
RPC(不然讲Dubbo干啥,它就是干这个的)
创建一个工程来统一管理接口和pojo,参考dubbo官网最佳实践
摘取dubbo官方一小部分原文
建议将服务接口、服务模型、服务异常等均放在 API 包中,因为服务模型和异常也是 API 的一部分,这样做也符合分包原则:重用发布等价原则(REP),共同重用原则(CRP)。
接下来我们按照官方建议来解决第一个问题
创建新模块: api-manager,用于统一管理我们的服务接口、服务模型、服务异常
将pojo和Service复制到我们的新项目中
其他工程里的pojo和Service接口我们都干掉
这时候项目必然报错,但是我们至少解决了第一个问题
怎么能把我们上面的项目里的pojo和接口引入呢?
这时候就要用到我们的Maven了(其实拷贝jar包也可以,但是太low了)
在提供者和消费者项目的pom中引入我们的api-manager
<dependency>
<groupId>com.shouwang</groupId>
<artifactId>api-manager</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
这样报错就消失了
接下来就可以开始着手解决第二个问题了
用Dubbo改造我们的项目分为以下几个步骤
将服务提供者注册到注册中心
服务消费者去注册中心订阅服务提供者的IP地址
以下依赖需要同时在消费者和提供者里引入
导入dubbo依赖(建议使用2.6.x,因为2.6是个分水岭)
<!-- dubbo -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>dubbo</artifactId>
<version>2.6.2</version>
</dependency>
导入Zookeeper客户端(2.6以后不是zkclinet而是curator)
<!-- curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>2.12.0</version>
</dependency>
配置dubbo(dubbo官方为我们提供了xml配置方式)
详情参照https://dubbo.apache.org/zh-cn/docs/user/quick-start.html
服务提供者provider.xml(放在resources下)
<?xmlversion="1.0" encoding="UTF-8"?>
<beansxmlns="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-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 提供方应用信息,用于计算依赖关系(同样的服务名字一定要一致,不同服务名字不能相同) -->
<dubbo:Applicationname="user-service"/>
<!-- 使用multicast广播注册中心暴露服务地址 -->
<dubbo:registryaddress="zookeeper://127.0.0.1:2181"/>
<!-- 用dubbo协议在20880端口暴露服务 -->
<dubbo:protocolname="dubbo" port="20880"/>
<!-- 声明需要暴露的服务接口 ref指向服务实现-->
<dubbo:serviceinterface="com.shouwang.apimanager.service.UserService" ref="userService"/>
<!-- 和本地bean一样实现服务 -->
<beanid="userService" class="com.shouwang.userservice.serviceImpl.UserServiceImpl"/>
</beans>
接下来按照官方给出的写一个main方法去读取我们的配置文件
publicclassProvider {
publicstatic void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = newClassPathXmlApplicationContext("provider.xml");
context.start();
System.in.read(); // 按任意键退出,防止应用终止
}
}
启动应用(可能需要修复一下我们之前的导包问题)
进入我们dubbo-admin项目,可以看到提供者多出一个
接下来我们来配置消费者consumer.xml
<?xmlversion="1.0" encoding="UTF-8"?>
<beansxmlns="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-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:applicationname="order-service" />
<!-- 使用multicast广播注册中心暴露发现服务地址 -->
<dubbo:registryaddress="zookeeper://127.0.0.1:2181" />
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:referenceid="userService" interface="com.shouwang.apimanager.service.UserService" />
</beans>
因为我们配置了一个bean,所以我们就可以使用依赖注入,将服务代理注进来,修改之前的消费者实现
//注意,这里还是使用的Spring中的Service(Dubbo后面会讲)
@Service
publicclassOrderServiceImpl implements OrderService {
@Autowired
UserService userService;
@Override
publicvoid createOrder(Integer userId) {
/*查询用户信息*/
Logger logger = LoggerFactory.getLogger(getClass());
logger.info(userService.getUser(1)+"");
}
}
因为我们使用了Spring注解,所以我们需要加入包扫描来发现我们的注解
修改consumer.xml
<?xmlversion="1.0" encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
<dubbo:applicationname="order-service" />
<!-- 使用multicast广播注册中心暴露发现服务地址 -->
<dubbo:registryaddress="zookeeper://127.0.0.1:2181" />
<!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
<dubbo:referenceid="userService" interface="com.shouwang.apimanager.service.UserService" />
<!--配置包扫描-->
<context:component-scanbase-package="com.shouwang.orderservice.serviceImpl"></context:component-scan>
</beans>
创建Consumer类
publicclassConsumer {
publicstatic void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = newClassPathXmlApplicationContext("consumer.xml");
context.start();
OrderService orderService = (OrderService)context.getBean(OrderService.class);// 获取远程服务代理
orderService.createOrder(1); // 执行远程方法
System.in.read();//防止退出
}
}
这里会报错,因为我们的User是要在网络上传输的,所以必须实现Serializable接口
修改后的User
@Data
publicclassUser implements Serializable {
privateInteger id;
privateString name;
privateString addr;
}
再次运行,成功完成一次RPC
同样进入dubbo-admin,得到以下结果
服务数:1 应用数:2 提供者数:1 消费者数:1
我的监控中心已经解压到E:dubbo-monitor-simple-2.0.0下
同样你可以在dubbo github主页上获取最新版本
打包方式和控制台相似
嫌打包麻烦也可以直接在assembly.bin文件夹里通过start.sh启动
启动后访问http://localhost:8080即可
然后在我们提供者和消费者xml配置中新增
<!--监控中心-->
<dubbo:monitorprotocol="registry"></dubbo:monitor>
开发环境下用我配置好的即可,但是生产环境下记得将conf目录下Zookeeper的路径以及端口配置好
这里不再赘述,更多详细说明可以参照官网https://dubbo.apache.org/zh-cn/docs/user/references/xml/dubbo-monitor.html
控制台和监控中心类似,2选1甚至不选都是可以的
SpringBoot倡导0配置开发,所以我们实际开发中Dubbo肯定为我们提供了Annotation(注解式开发),来简化我们的开发过程
为了让我写的教程成为参考手册(减少各个章节之间的关联,成为松耦合的教程),我们重新创建模块并进行开发
以下是新的假设场景
开发一个云笔记项目(类似于有道云笔记)
为了简化我们的教程,我们只编写以下两个服务
笔记服务
用户服务
创建笔记的时候我们需要消费用户服务以得到创建者的信息
新建两个模块(加springboot前缀是为了区分之前的xml配置项目,实际生产环境下名字自取)
在自定义目录下创建一个空文件夹
创建完成后用IDEA打开指定项目
在文件夹中创建一个Maven项目(这是api服务)
springboot-user-api
创建结束后需要对pom文件进行改造,具体改造参照源码
<?xmlversion="1.0" encoding="UTF-8"?>
<projectxmlns="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.zfbgt</groupId>
<artifactId>springboot-user-api</artifactId>
<version>1.0.0-SNAPSHOT</version>
<!--指定打包方式-->
<packaging>jar</packaging>
<properties>
<!--指定编码集-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!--指定java版本-->
<java.version>1.8</java.version>
</properties>
</project>
在源码包下新建包(遵循包命名规范):com.zfbgt.hello.dubbo.service.user.api
然后在该包下创建UserService接口
packagecom.zfbgt.hello.dubbo.service.user.api;
publicinterfaceUserService {
String sayHi();
}
定义好接口后我们创建第二个项目[Spring Initializer]
创建好了后参照官网给出的sample修改我们的pom文件
在引入API项目的时候可能会找不到,原因是因为我们没有安装该项目,使用mvn clean install 命令即可安装我们的项目
springboot-user-service
springboot-note-service
创建过程不再赘述
当我们删除了一个module并重新创建的时候,我们会发现再次打开项目会提示"These modules have been removed from Maven structure:
'springboot-user-api'"
这时File-Settings-Maven-lgnored Files
把打勾的pom.xml去掉就可以了