zookeeper安装—>点我鸭
一. Dubbo出现的背景
单体应用
所有功能都在一个应用之中,机器数量在1-10之间
垂直应用
将应用按照功能进行划分,拆分成互不相干的小应用,应用之间应该没有交互
分布式应用
“合久必分”,虽然提供的是独立的服务,但是可以被其他应用或服务所调用
SOA = Service-Oriented Architecture 面向服务的架构
通过定义接口,来提供调用方式,实际执行逻辑是被调用服务(项目B)中编写的代码
项目A AService --> 项目B BService sayHello(String msg)
早期的SOA实现方式:
1)WebService (注册、发现、调用)
此时通信的数据格式为xml,通信协议也多是http或者https
2)ESB = Enterprise Service Bus 企业服务总线
通过管道,将各服务进行整合,以更好的通信
二. 分布式系统通信方式
1.RMI
RMI = Remote Method Invocation 远程方法调用
客户端将要调用的方法及参数,打包为辅助对象,通过网络socket,发送给服务端辅助对象
服务端接收后,会进行解包,找出真正被调用的方法,然后将执行结果,依次再返回回去
服务端辅助对象进行打包,然后客户端辅助对象进行解包,结果返回给真正的调用者
/**
* RMI方式的接口声明
* 1)接口本身继承Remote
* 2)被调用的方法也要抛出相关的异常 RemoteException
* 因为底层需要经过网络通信,而通信是有风险的
*/
public interface HelloService extends Remote {
String sayHello(String msg) throws RemoteException;
}
/**
* RMI接口的实现类使用说明
* 1)需要继承 UnicastRemoteObject远程对象类
* 2)因为 UnicastRemoteObject 的构造函数抛出了异常所以子类也需要重写构造函数
* 3)由于此方法的参数和返回值都需要在网络上传输所以需要可序列化
*/
public class HelloServiceImpl extends UnicastRemoteObject
implements HelloService {
// 序列化的版本号
private static final long serialVersionUID = 5185759308961857565L;
public HelloServiceImpl() throws RemoteException {
}
@Override
public String sayHello(String msg) throws RemoteException {
return "Hello, are you talking about '" + msg + "'?";
}
}
/**
* 暴露服务
* 提供可被调用的端口
*/
public class RMIServer {
public static void main(String[] args) {
try {
// 通过本地的注册中心
LocateRegistry.createRegistry(9090);
// 注册接口实现类 到具体的通讯地址下
HelloService helloService = new HelloServiceImpl();
Naming.bind("rmi://127.0.0.1:9090/RMIServer",helloService);
System.out.println("rmi服务端启动成功");
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 调用RMI的客户端
*/
public class RMIClient {
public static void main(String[] args) {
HelloService helloService = null;
try {
// 寻找服务端的路径 和 具体的实现逻辑
helloService = (HelloService) Naming.lookup("rmi://127.0.0.1:9090/RMIServer");
Object result = helloService.sayHello("rmi demo success");
System.out.println("rmi客户端接收结果为:" + result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
实现效果:
2.RPC
IPC = Inter-Process Communication 进程间通信
进程是计算机系统分配资源的最小单位,对于每个进程而言,都是资源隔离的
通信是解决,不同进程间相互访问资源的需求
LPC = Local Procedure Call 本地过程调用
RPC = Remote Procedure Call 远程过程调用
RPC真正的目的,是像调用本地方法一样去调用远程方法,而且不需要关心方法部署在哪里,这样才能够解耦服务
简单说,RPC就是从一台机器通过参数传递的方式,调用另一台机器上的方法,并得到返回结果
常用RPC框架
1) Dubbo,阿里开发,基于Spring和Netty,是当前使用最广泛的RPC框架
2) brpc,百度开发,“baidu-rpc”,支持多种协议,性能优良
3) grpc,谷歌开发,基于Netty,在人工智能领域有广泛应用,服务于tensorflow的底层通信
4) Thrift,脸书开发,已开源给apache,有一定的应用范围
三.Dubbo
1.Dubbo架构图
节点 | 角色说明 |
---|---|
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的服务消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
2.注册中心Zookeeper
最早由雅虎开发用来解决分布式系统中的一致性问题
包括配置管理、集群的扩容和缩容、分布式锁等等
1) 官网下载安装包,将tar.gz文件解压缩
2) Zookeeper也需使用本地的java环境,java_home的地址不能包含特殊字符,如中文或括号等等
3) 在本地找到一个存放zookeeper的地址,然后进入conf目录下,拷贝一份zoo_sample.cfg,命名为zoo.cfg
# The number of milliseconds of each tick
# tick是zookeeper计时的时间单位 这里表示2000ms = 2s
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
# 同步限制时间 (心跳时间) 单位是5tick = 10s
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
#数据文件夹
dataDir=/root/zookeeper/data
#日志文件夹
dataLogDir=/root/zookeeper/logs
# the port at which the clients will connect
# 客户端连接zookeeper的端口号
clientPort=2181
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
## Metrics Providers
#
# https://prometheus.io Metrics Exporter
#metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
#metricsProvider.httpPort=7000
#metricsProvider.exportJvmInfo=true
4) 启动服务并验证可以被连接
Windows下环境
进入到bin目录下执行zkServer.cmd,启动成功后,再打开新的窗口,在bin目录下执行zkCli.cmd看到命令行窗口
亦可Linux环境
测试进入到bin目录下执行zkServer.sh,启动成功后,再打开新的窗口,在bin目录下执行zkCli.sh
3.逃不了的HelloWorld
1) demo – spring方式集成
提供一个可被调用的接口
提供方,实现接口的方法逻辑,启动应用程序,接收消费方的调用
消费方,确认要调用的接口,找到注册中心,调用提供方,获取接口的返回结果
a、启动zookeeper
b、引入相关依赖
c、声明接口及其实现类
d、创建提供方和消费方的应用程序
public interface GreetingsService {
String sayHi(String name);
}
public class GreetingsServiceImpl implements GreetingsService {
@Override
public String sayHi(String name) {
return "hi, " + name;
}
}
//提供者
public class Application {
//先获取zookeeper部署的ip地址
private static String zookeeperHost = System.getProperty("zookeeper.address", "121.196.47.73");
public static void main(String[] args) throws Exception {
// 创建服务配置 服务对应的接口类 设置为泛型
ServiceConfig<GreetingsService> service = new ServiceConfig<>();
// 设置应用程序的名字
service.setApplication(new ApplicationConfig("first-dubbo-provider"));
// 设置注册中心 指定zookeeper的连接地址
service.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
// 设置提供的接口
service.setInterface(GreetingsService.class);
// 设置具体的实现类
service.setRef(new GreetingsServiceImpl());
// 设置完成 执行导出命令
service.export();
System.out.println("dubbo service started");
// 让线程处于挂起的状态 一直等待接收调用端的连接
new CountDownLatch(1).await();
}
}
//消费者
public class Application {
private static String zookeeperHost = System.getProperty("zookeeper.address", "121.196.47.73");
public static void main(String[] args) {
// 创建关联配置 要调用的接口仍然作为泛型
ReferenceConfig<GreetingsService> reference = new ReferenceConfig<>();
// 设置应用程序的名字
reference.setApplication(new ApplicationConfig("first-dubbo-consumer"));
// 设置注册中心
reference.setRegistry(new RegistryConfig("zookeeper://" + zookeeperHost + ":2181"));
// 设置要调用的接口
reference.setInterface(GreetingsService.class);
// 通过get方法 获取到远程的接口调用
GreetingsService service = reference.get();
// 接收到远程接口的返回结果
String message = service.sayHi("dubbo demo");
System.out.println(message);
}
}
实现效果:
2) demo – springboot方式集成
Springboot集成Dubbo参考地址
a)引入依赖(dubbo-springboot、 dubbo-zookeeper、要使用的api的依赖)
public interface DemoService {
String sayHello(String name);
}
b)实现provider, 实现接口逻辑,增加配置参数
// 说明这个类是作为dubbo的服务被调用的
@DubboService(version = "1.0.0")
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
return "Hello," + name;
}
}
# 配置dubbo涉及的相关参数
spring.application.name=dubbo-demo-provider
# 配置dubbo服务的扫描路径
dubbo.scan.base-packages=com.pz.provider.service
# dubbo协议相关信息
dubbo.protocol.name=dubbo
dubbo.protocol.port=2345
# dubbo注册中心地址
dubbo.registry.address=zookeeper://121.196.47.73:2181
c)实现consumer,注意配置类和主程序入口
@SpringBootApplication
public class DubboDemoConsumerApplication {
// 对于调用端 使用的注解为DubboReference
// 对于提供端 使用的注解为DubboService
@DubboReference(version = "1.0.0")
private DemoService demoService;
public static void main(String[] args) {
SpringApplication.run(DubboDemoConsumerApplication.class, args);
}
// ApplicationRunner 在程序启动后 执行代码逻辑
@Bean
public ApplicationRunner runner(){
return args -> System.out.println(
demoService.sayHello("dubbo-springboot"));
}
}
server.port=8989
spring.application.name=dubbo-demo-consumer
dubbo.registry.address=zookeeper://121.196.47.73:2181