项目经理(leader)
产品经理:制作产品的原型图,给定需求。
UI:画图
前端:前台的流程控制,跳转逻辑,页面效果。
后端:开发功能上实现的一些逻辑。
测试:测试你开发的功能。
什么是分布式?什么是集群?
广义上的分布式就包括昨天讲的Nginx,一个Nginx代理多个服务器。以及微服务。
狭义上的分布式指的就是微服务:每个服务都是由一个单独的应用来提供,服务与服务之间进行轻量级通信,这个通信的框架就叫Dubbo。
之前所有服务都在同一个应用中的时候,每个服务都在同一个jvm进程中,我们用Spring完成bean的控制。如果在订单模块想使用用户模块的信息,直接通过@Autowired注入,因为他们都在同一个Spring容器中。
现在将一个应用拆分成了几个不同的服务,不同的服务(不同的进程)进行通信,需要使用网络通信。
之前的前后端分离时,前段项目和后段项目之间的通信协议是http协议。
Dubbo支持这些协议:
大多使用的是Dubbo协议,Dubbo是一个传输层协议。
Dubbo解决了这些进程(服务)之间的跨进程调用问题。但是像链路追踪、分布式事务这些,Dubbo并没有解决这些问题。
而springcloud把一整套的微服务的解决方案都给你了。
Dubbo默认使用的是Dubbo协议(传输层协议)
SpringCloud使用的是http协议(应用层协议)
Dubbo协议调用起来要比http协议快的:因为应用层的数据要到传输层是要拆包的,会有时间损耗的。
下面讲一下spring和Dubbo的整合:
代码见E:\WangDao\Code7\day1_dubbo\spring-dubbo
目录结构:
配置:
provider中的application-context.xml:
consumer中的application-context.xml:
consumer中需要有一个和provider一模一样的接口(包名+类名一模一样)(DemoService),这样consumer才能访问到provider中的DemoService。
DemoService:
package com.cskaoyan.demo;
public interface DemoService {
String getDetail(String name);
}
consumer并没有真正的写一个DemoServiceImp,而是调用provider的DemoServiceImp来供自己使用。
DemoServiceImp:
package com.cskaoyan.demo.impl;
import com.cskaoyan.demo.DemoService;
/**
* @author: jia.xue
* @Email: xuejia@cskaoyan.onaliyun.com
* @Description
**/
public class DemoServiceImpl implements DemoService {
public String getDetail(String name) {
System.out.println("收到name:" + name);
return name + ":刘师傅真胖!";
}
}
所以在启动consumer之前应当先启动provider。
否则会有这样的报错信息:failed to connect to server /127.0.0.1:20880, error message is:Connection refused
我们写代码的时候可能会遇到这种报错信息:No such any registry to export service in provider 192.168.45.1 use dubbo version 2.5.3, Please add <dubbo:registry address="…" /> to your spring config.If you want unregister, please set <dubbo:service registry=“N/A” />
这幅图是从Dubbo官网下载下来的:provider向外暴露接口的时候,可以将接口暴露到Registry(注册中心)中,也可以暴露给consumer,直接暴露给consumer需要增加一个配置:<dubbo:service registry="N/A" />
这个实例对象,其实不是真正的DemoServiceImpl对象,而是一个代理对象。
代理对象是一个DemoService 的实例,这个代理对象里面有什么东西呢?
这个代理对象里面放的是 真正提供服务的对象的url地址
Provider:
package com.cskaoyan.demo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
/**
* @author: jia.xue
* @Email: xuejia@cskaoyan.onaliyun.com
* @Description
**/
public class Provider {
public static void main(String[] args) {
// applicationContext 这个是什么? 这个就是Spring容器对象
//No such any registry to export service in provider 192.168.45.1 use dubbo version 2.5.3, Please add <dubbo:registry address="..." /> to your spring config.
// If you want unregister, please set <dubbo:service registry="N/A" />
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");
// 启动容器
applicationContext.start();
System.out.println("启动成功。。。");
//保持让容器处于启动的状态
try {
// 系统阻塞等待输入
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Consumer:
package com.cskaoyan.demo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author: jia.xue
* @Email: xuejia@cskaoyan.onaliyun.com
* @Description
**/
public class Consumer {
public static void main(String[] args) {
// 初始化consumer容器
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");
//启动
applicationContext.start();
// 从容器里面去取一个bean——"demoService"
//failed to connect to server /127.0.0.1:20880, error message is:Connection refused
//这个实例对象,其实不是真正的DemoServiceImpl对象,而是一个代理对象
// 代理对象是一个DemoService 的实例,这个代理对象里面有什么东西呢?
// 这个代理对象里面放的是 真正提供服务的对象的url地址
DemoService demoService = (DemoService) applicationContext.getBean("demoService");
// 一旦我们去使用代理对象调用方法,那么他就会调用这个代理对象里面封装的url地址的对象的方法
String response = demoService.getDetail("松哥冲冲冲!");
// 代理对象(dubbo://127.0.0.1:20880).getDetail ---网络--> 访问 服务提供者的真正的对象实例
System.out.println(response);
}
}
先启动Provider在启动Consumer,Consumer就会调用Provider中的接口。
下面讲一下springboot和Dubbo的整合:
- 导包
provider2:
dubbo 2.6.0和2.7.1的整合是有一些区别的。我们现在先用2.6.0
和spring整合的dubbo相比,主要区别在于配置
配置:
provider2中的application.properties:
DemoServiceImpl:
其中@Service注解是来自:import com.alibaba.dubbo.config.annotation.Service;
@Component表示注入到容器中,相当于下面的bean标签
@Service(interfaceClass = DemoService.class)表示下面的配置接口及其具体实现。
对比provider中的application-context.xml:
consumer2中的application.properties:
在ThirdService中调用DemoService,在成员变量demoService上写注解
ThirdService相当于工具人,
对比consumer中的application-context.xml:
注意:在springboot项目中,如果想启动dubbo,不管provider还是consumer,必须在启动类上加注解:@EnableDubboConfiguration
ProviderApplication:
package com.cskaoyan.sb.provider;
import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import java.io.IOException;
@SpringBootApplication
@EnableDubboConfiguration // 启动Dubbo服务
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
try {
System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}
}
ConsumerApplication:
package com.cskaoyan.sb.consumer;
import com.alibaba.dubbo.spring.boot.annotation.EnableDubboConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
@SpringBootApplication
@EnableDubboConfiguration // 启动Dubbo服务
public class ConsumerApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = SpringApplication.run(ConsumerApplication.class, args);
applicationContext.start();
ThirdService thirdService = applicationContext.getBean(ThirdService.class);
String response = thirdService.say("ligenli daqi");
System.out.println(response);
}
}
注意:url我们都是写死的,一旦provider暴露的端口号变了,consumer就无法从provider中获取信息了。
还记得registry(注册中心)么?
注册中心就是用来做两个服务之间的协调工作的。我们现在使用的注册中心叫zookeeper。
zookeeper是一个分布式协调中间件,类似于Tomcat、mysql、redis等,需要单独启动。
- provider2、consumer2导包
- 将provider2中的application.properties文件稍作修改,开启注册中心
同时将consumer2中的application.properties修改:
3. 这句代码也不需要了
以上都是基于dubbo2.6版本的,接下来我们写基于dubbo2.7版本的。
在dubbo-demo2这个Module下新建3个Module:provider3、consumer3、common。
其中common下存放provider3和consumer3中共同的部分(DemoService)。
-
common
common的pom文件中导入依赖,同时将其打包为jar包,让common作为jar包让provider3和consumer3去依赖。 -
在provider3和consumer3中将common这个jar包引入,common里面的依赖provider3和consumer3都能依赖,这就是依赖传递。
同时provider3和consumer3中都有了common中写的代码。
provider3和consumer3的pom:
同时启动类中的这个注解不用写了
配置包扫描路径:
provider3:
consumer3:
provider和consumer中导包:
下面两个包都是为上面的zookeeper服务的。
启动测试即可。
启动顺序:zookeeper、provider、consumer
启动的时候一定要看启动日志是否打印出来,打印出来的话才表示启动成功了。