学习之前,确保有以下知识基础:

  • Java网络编程
  • Socket传输数据
  • IO流

rpc简介及实现

rpc是remote procedure call的简写,意思为远程过程调用。

rpc应用较多的情景是分布式开发,那什么是分布式开发呢?

原本我也是想自己解释的,奈何网上大佬解释得很清楚了,这里就不献丑了,建议阅读完下面推荐的几篇再继续往下

刚开始的时候,服务和调用都是在同一机器,这叫本地过程调用

之后,由于客户量增长,一个服务器并不能满足要求,之后便是把调用和服务分开,分别部署在不同的机器,负责调用服务方法的称之为客户机,负责提供服务方法的称为服务机

上图的原理可能步骤有点多,但是只要记住一点,客户机是把数据通过Socket或者是其他协议传递到了服务机,让服务机进行处理,从而以相同的协议方式把数据传递回来

如何实现一个简单的RPC一文中,大佬已经实现了一个简洁的rpc框架,然后对于这个rpc框架,并提出来的一些可以优化的点:

1. 缺乏通用性

我通过给Calculator接口写了一个CalculatorRemoteImpl,来实现计算器的远程调用,下一次要是有别的接口需要远程调用,是不是又得再写对应的远程调用实现类?这肯定是很不方便的。

2、集成Spring

在实现了代理对象通用化之后,下一步就可以考虑集成Spring的IOC功能了,通过Spring来创建代理对象,这一点就需要对Spring的bean初始化有一定掌握了。

3、长连接or短连接

总不能每次要调用RPC接口时都去开启一个Socket建立连接吧?是不是可以保持若干个长连接,然后每次有rpc请求时,把请求放到任务队列中,然后由线程池去消费执行?只是一个思路,后续可以参考一下Dubbo是如何实现的。

4、 服务端线程池

我们现在的Server端,是单线程的,每次都要等一个请求处理完,才能去accept另一个socket的连接,这样性能肯定很差,是不是可以通过一个线程池,来实现同时处理多个RPC请求?同样只是一个思路。

5、服务注册中心

正如之前提到的,要调用服务,首先你需要一个服务注册中心,告诉你对方服务都有哪些实例。Dubbo的服务注册中心是可以配置的,官方推荐使用Zookeeper。如果使用Zookeeper的话,要怎样往上面注册实例,又要怎样获取实例,这些都是要实现的。

6、负载均衡

如何从多个实例里挑选一个出来,进行调用,这就要用到负载均衡了。负载均衡的策略肯定不只一种,要怎样把策略做成可配置的?又要如何实现这些策略?同样可以参考Dubbo,Dubbo - 负载均衡

7、结果缓存

每次调用查询接口时都要真的去Server端查询吗?是不是要考虑一下支持缓存?

8、多版本控制

服务端接口修改了,旧的接口怎么办?

9、异步调用

客户端调用完接口之后,不想等待服务端返回,想去干点别的事,可以支持不?

10、优雅停机

服务端要停机了,还没处理完的请求,怎么办?

PS:使用rpc的时候,需要考虑到网络问题,需要采用重试机制

由上述的这些问题,之后便是出现了一些优秀的rpc框架,如dubbo、spring cloud等

dubbo简介

Dubbo是阿里巴巴开源的基于 Java 的高性能 RPC(远程过程调用) 分布式服务框架(SOA),致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案,其内部使用了 Netty、Zookeeper,保证了高性能高可用性。

dubbo结构图:

节点 角色说明
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次数和调用时间的监控中心
Container 服务运行容器

其中,注册中心Registry和监控中心Monitor都是可选的,所以,我们下文先简单实现dubbo(点对点传输数据)

<dependency>
<groupId>com.starsone</groupId>
<artifactId>dubbo-api</artifactId>
<version>0.0.1</version>
</dependency>

dubbo简单实现

项目说明:

项目基于spring boot,分为三个部分,apiconsumerprovider

  • api主要是用来声明一些服务的接口(maven项目)
  • provider则是对服务接口的具体实现(spring boot项目,通过maven依赖api项目)
  • consumer则是远程调用provider提供的服务接口(spring boot项目,通过maven依赖api),

本质上consumer相当于客户机,而provider相当于客户机

1.新建项目

使用IDEA,建立一个空白的项目,之后新建module

之后IDEA会弹出一个新建module的窗口

依次新建api、provider、cousmer三个module

api选择maven项目,之后填写相关的包名信息直接新建即可(不需要选择具体的maven结构),而另外两个则是spring boot项目,选择spring initializr新建即可,同样,不要勾选其他的依赖,填写好包名相关信息新建即可

2.api项目声明服务接口

在api项目中,我们新建一个CalculatorService接口,里面定义一个add的方法

public interface CalculatorService {
int add(int a,int b);
}

3.配置api项目的依赖

原本,之后的provider和consumer项目都是需要引用dubbo-spring-boot-starter这个依赖,dubbo-spring-boot-starter依赖中已经包含了dubbo依赖,这样就可以不需要写dubbo的依赖了

由于之后我们的provider和consumer项目都是需要引用api这个项目,所以,我们可以把provider和consumer所需要的依赖dubbo-spring-boot-starter添加到api这个项目中

之后的provider和consumer项目也就是依赖了api项目,也成功依赖了dubbo-spring-boot-starter

<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>2.7.5</version>
</dependency>

4.provider和consumer项目引用api项目依赖

由于之前我们创建的api项目是maven项目,所以添加依赖就很简单,在provider和consumer各自的pom.xml添加依赖即可

5.provider实现api中的服务接口

我们在provider项目中新建一个类CalculatorServiceImpl,去实现CalculatorService接口

@Service(interfaceName = "calculatorService")
class CalculatorServiceImpl:CalculatorService {
override fun add(a: Int, b: Int): Int {
val result = a+b
println("$a+$b=$result")
return result
}
}

注意,这里的Service注解是dubbo包里面的注解,而不是spring中的Service,定义接口名interfaceNamecalculatorService,方便之后容器进行查找

6.配置provider项目

我们需要修改spring boot的配置文件,这里我使用yml的形式进行配置,阅读比较舒适

spring:
application:
name: dubbo-provider-application
dubbo:
scan:
#扫描指定包是否包含有dubbo中Service注解的类
base-packages: com.starsone.provider.service
protocol:
name: dubbo #协议,默认为dubbo(其他协议webserovice、Thrift、Hessain、http)
port: 12345 #端口,默认为20880
registry:
address: N/A #不需要注册中心

PS:如果不想在配置文件制定扫描包含有Service注解的类,可以在provider项目中的application类中添加开启dubbo自动扫描的注解@EnableDubbo

provider项目结构图:

7.运行provider

由于我们没有引入注册中心,所以得先运行provider,获得ip地址

之后consumer项目中,才能让springr容器去根据ip地址+端口号去找到对应的实例并自动装载

由输出日志,我们可以看到ip地址

8.consumer获得service对象

@Component
class MyRunner:ApplicationRunner {
@Reference(url ="dubbo://192.168.52.1:12345",interfaceName = "calculatorService" )
private lateinit var calculatorService: CalculatorService override fun run(args: ApplicationArguments?) {
println(calculatorService.add(5,14))
}
}

这里,由于是为了简单考虑,没有使用web依赖,所以,使用了ApplicationRunner这个接口进行测试,spring容器在加载完成会自动回调此接口

Reference注解是dubbo中的注解,consumer项目运行之后,consumer中的dubbo就会根据此url和一些其他的信息进行数据的传递,远程调用provider中的服务,之后,provider接收数据并进行处理,返回数据给consumer,是不是有了rpc的感觉?

9.配置consumer及测试

配置的话,只配置了应用的名称

之后,我们运行consumer的application,可以看到结果

同样,在provider项目,也是打印出了consumer项目传递过来的参数

引入注册中心

前面的实现,是没有注册中心的,属于一种直连的方式,但是,实际上,分布式开发,具有多台服务机

客户机应该是向注册中心请求,由注册中心查询当前空闲的服务机,并根据某种策略,选择其中一台服务机,将其ip地址返回给客户机,之后客户机通过ip地址,与该服务机进行连接,进行rpc操作

dubbo框架中,推荐使用ZooKeeper作为注册中心

ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

1.下载zookeeper

http://mirror.bit.edu.cn/apache/zookeeper/

注意,这里下载的版本最好与项目中的依赖版本一致

2.导入zookeeper依赖

我们需要修改api项目中的依赖,这样provider和consumer两个项目的依赖也是得以修改

<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.14</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty</artifactId>
</exclusion>
</exclusions>
</dependency> <!-- Zookeeper客户端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>4.2.0</version>
</dependency>

3.配置provider和consumer的注册中心

provider:

consumer:

4.取消consumer指定url

由于我们使用的是注册中心,所以,不需要指定url了,把Reference注解中的url删掉

5.运行zookeeper

解压下载的zookeeper压缩包,进入到conf目录,把zoo_sample.cfg文件改为zoo.cfg

进入bin目录,点击zkserver.cmd文件,运行zookeeper

6.运行provider和consumer

先运行provider,之后运行consumer,可以看到结果

本篇文章也是折腾了几天,参考了十几篇文章,一步步测试才弄成功,有些知识点并没有太深入,像dubbo控制台、监控中心等如何搭建,后期学习的时候再进行补充说明吧

参考

rpc框架dubbo学习入门及环境搭建(spring boot+Kotlin)的更多相关文章

  1. Spring Boot入门(一):搭建Spring Boot项目

    从本篇博客开始,我们开始进入Spring Boot的世界,它的出现使Spring的开发变得更加简洁,因此一经推出受到众多程序员的喜爱. 作为Spring Boot系列的第一篇博客,我们先来讲解下如何搭 ...

  2. Dubbo学习之简单环境搭建

    Dubbo服务的发展和作用: 首先,看下一般网站架构随着业务的发展,逻辑越来越复杂,数据量越来越大,交互越来越多之后的常规方案演进历程. 其次,当服务越来越多之后,我们需要做哪些服务治理? 最后,是d ...

  3. 01-S3C2440学习入门概念+环境搭建【转】

    本文转载自:http://blog.csdn.net/fengyuwuzu0519/article/details/54754812 一.心得: 这两年学过很多东西,有点杂,总感觉不够踏实,于是准备写 ...

  4. 前端框架vue学习笔记:环境搭建

    兼容性 不兼容IE8以下 Vue Devtools 能够更好的对界面进行审查和调试 环境搭建 1.nodejs(新版本的集成了npm)[npm是node包管理 node package manager ...

  5. 一个入门rpc框架的学习

    一个入门rpc框架的学习 参考 huangyong-rpc 轻量级分布式RPC框架 该程序是一个短连接的rpc实现 简介 RPC,即 Remote Procedure Call(远程过程调用),说得通 ...

  6. 新手嘛,先学习下 Vue2.0 新手入门 — 从环境搭建到发布

    Vue2.0 新手入门 — 从环境搭建到发布 转自:http://www.runoob.com/w3cnote/vue2-start-coding.html 具体文章详细就不搬了,步骤可过去看,我这就 ...

  7. Spring框架学习笔记(8)——spring boot+mybatis plus+mysql项目环境搭建

    之前写的那篇Spring框架学习笔记(5)--Spring Boot创建与使用,发现有多小细节没有提及,,正好现在又学习了mybatis plus这款框架,打算重新整理一遍,并将细节说清楚 1.通过I ...

  8. RPC 框架 Dubbo 从理解到使用(一)

    技术架构演变 单一应用架构 通俗地讲,"单体应用(monolith application)"就是将应用程序的所有功能都打包成一个独立的单元.当网站流量很小时,只需一个应用,将所有 ...

  9. JAVA WEB快速入门之环境搭建

    前言 我是一直致力于:.NET技术栈.WEB前端.架构设计相关的开发与管理工作,但因国内大环境影响及公司技术方向发生转变(由.NET全部转为JAVA),需要熟练掌握JAVA WEB相关的知识,故我也得 ...

随机推荐

  1. linux中用户和用户组的概念以及查看命令

    Linux 是多用户多任务操作系统,换句话说,Linux 系统支持多个用户在同一时间内登陆,不同用户可以执行不同的任务,并且互不影响. 例如,某台 Linux 服务器上有 4 个用户,分别是 root ...

  2. 小码哥哥 FastJson--阿里巴巴公司开源的速度最快的Json和对象转换工具

    转载地址:http://www.oschina.net/code/snippet_228315_35122?_t_t_t=0.4667952097048127 class User{ private ...

  3. Jenkins 2 如何使用 PowerShell 以及自定 build fail (指定 exit code)

    Jenkins 除了用來做為 CI(持續性整合) 工具外,也可以與其他 plugin 配合達成其他目的(e.g.IIS restart.檔案壓縮備份-),今天就來看看可以怎麼與 PowerShell ...

  4. MOOC(2)-Django开发get、post请求,返回json数据

    1.对get请求直接返回参数 如果请求多个参数,也只能返回一个参数,这里只返回了username参数 如果想要返回多个参数值,可以返回json格式数据 2.对get请求返回json数据 # views ...

  5. webpack debug

    chrome地址栏输入:chrome://inspect/#devices 点击 Open dedicated DevTools for Node 在需要打断点的地方加入debugger 控制台输入 ...

  6. Intellij IDEA创建 Web 项目

    快速构建 Web 项目 打开IDEA,新建Project,左边菜单栏选择 Maven,直接点 Next 选择GroupId和ArtifactId 选择项目名称,默认会填上工程位置.模块姓名等,直接点F ...

  7. linux 的uuid码

    在提到这个之前,有个概念,就是什么是uuid呢? UUID码全称是通用唯一识别码 (Universally Unique Identifier, UUID),它 是一个软件建构的标准,亦为自由软件基金 ...

  8. AJAX学习小结

    12345678910 $.ajax({ "url":"", //访问路径 "data":"", // 需要传输的数据 ...

  9. 5,Hadoop中的文件

    1,文件结构 · bin:脚本和命令目录. · etc:配置文件目录. · sbin:命令目录,主要包含HDFS和YARN中各类服务的启动和关闭,依赖于bin中的脚本. · share:各个模块编译后 ...

  10. K-means真的不能使用曼哈顿距离吗?

    问题 说到k-means聚类算法,想必大家已经对它很熟悉了,它是基于距离计算的经典无监督算法,但是有一次在我接受面试时,面试官问了我一个问题:“k-means为什么不能使用曼哈顿距离计算,而使用欧式距 ...