消息队列高手课
李玥
美团高级技术专家
51348 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 42 讲
进阶篇 (21讲)
消息队列高手课
15
15
1.0x
00:00/00:00
登录|注册

34 | 动手实现一个简单的RPC框架(四):服务端

你好,我是李玥。
上节课我们一起学习了如何来构建这个 RPC 框架中最关键的部分,也就是:在客户端,如何根据用户注册的服务接口来动态生成桩的方法。在这里,除了和语言特性相关的一些动态编译小技巧之外,你更应该掌握的是其中动态代理这种设计思想,它的使用场景以及实现方法。
这节课我们一起来实现这个框架的最后一部分:服务端。对于我们这个 RPC 框架来说,服务端可以分为两个部分:注册中心和 RPC 服务。其中,注册中心的作用是帮助客户端来寻址,找到对应 RPC 服务的物理地址,RPC 服务用于接收客户端桩的请求,调用业务服务的方法,并返回结果。

注册中心是如何实现的?

我们先来看看注册中心是如何实现的。一般来说,一个完整的注册中心也是分为客户端和服务端两部分的,客户端给调用方提供 API,并实现与服务端的通信;服务端提供真正的业务功能,记录每个 RPC 服务发来的注册信息,并保存到它的元数据中。当有客户端来查询服务地址的时候,它会从元数据中获取服务地址,返回给客户端。
由于注册中心并不是这个 RPC 框架的重点内容,所以在这里,我们只实现了一个单机版的注册中心,它只有客户端没有服务端,所有的客户端依靠读写同一个元数据文件来实现元数据共享。所以,我们这个注册中心只能支持单机运行,并不支持跨服务器调用。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《消息队列高手课》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(13)

  • 最新
  • 精选
  • 益军
    您好哈,提个疑问: 服务端业务方法不应该在channelRead0中执行,会导致netty ioEvent线程阻塞,应该异步提交到业务线程池执行 workers.execute(() -> { Command response = handler.handle(request); if (null != response) { channelHandlerContext.writeAndFlush(response).addListener((ChannelFutureListener) channelFuture -> { if (!channelFuture.isSuccess()) { logger.warn("Write response failed!", channelFuture.cause()); channelHandlerContext.channel().close(); } }); } else { logger.warn("Response is null!"); } }); Command response = handler.handle(request);

    作者回复: 在实际生产过程中,很多情况是需要这样处理的。避免阻塞IO线程。

    12
  • Gred
    来交作业啦【https://github.com/Gred01/simple-rpc-framework/tree/nameservice】,其实本应该在周五就写好了,现在写的demo支持mysql和oracle,初始化sql在rpc-netty底下init-sql.md。

    作者回复: 交作业的都是好同学,👍! 一个建议:使用PreparedStatement,不要用字符出拼SQL,会有SQL注入漏洞。

    2
    7
  • z.l
    请教下老师,如果要实现一个可供生产环境大规模集群使用的注册中心,JDBC协议是不是就不太合适了?这种情况下一个注册中心要满足哪些要求呢?个人盲猜:可多台部署、基于tcp协议最好也是netty实现、彼此之间要保证数据一致性(好像也不用强一致),不知道理解对不对

    作者回复: 大致的要求就是: 可用性:不能因为某个节点故障导致注册中心不可以; 数据一致性:能保证顺序一致性一般就可以满足需求了。 性能:server节点状态变更后,能尽快更新。 另外,大规模集群情况下,需要考虑业务系统上下线时,注册中心的性能问题。比如:一个几千个节点的微服务上线,会重启几千个Server节点,这时候注册中心需要更新大量的数据。

    2
  • zero
    如果服务端挂掉了,怎么通知NameService呢?

    作者回复: 这个问题在我们的demo中并没有解决。实际在生产环境中,有些注册中心会定期检查服务端的状态,但是即使这样也不能保证注册中心中维护的状态和服务端实际的状态实时同步。 解决这个问题,更多的是依靠rpc框架客户端的自动重试策略,比如,请求某个服务端实例超时后,立即换一个实例自动重试。

    2
  • 南山
    抓耳挠腮了两天,还没开始动手,不知道怎么下手~

    作者回复: 先把课后思考题完成了

    2
    2
  • 张小勋
    老师 你好~ 本人是net的 最近刚下了 git 的代码 去看了下~有些写法java和net 还是有区别的 问几个问题 希望老师能够作答一下 首先:helloServiceapi 项目中 建了一个接口 这个接口在服务端去实现 客户端也用到了~ 问下这个接口 在正常的使用中 都是服务端定义好 去给客户端 去使用的么 第二点:就是在服务端 服务端启动的时候 这个demo 中 是自己去实例化了HelloServiceImpl对象 如果在生产环境中 是不是启动的时候 通过反射 去实例化 那些特定的对外提供的服务 HelloService这样的接口 是不是也要做下标识 是这个思路么 最后 给自己立下个flag 这个月 自己会去 用netcore+netty+zookeeper 去实现一个RPC 多谢老师

    作者回复: 准确的说,应该是实现定义好接口,服务端和客户端都需要使用这个接口;

  • kim118000
    Method method = serviceProvider.getClass().getMethod(rpcRequest.getMethodName(), String.class); 每次请求都用反射获取method,有没有性能损耗,是不是存起来,请问老师这部分生产级别怎么处理的?

    作者回复: JVM对反射的优化已经很好了,这部分的性能损耗并不是很大,所以一般不用特别的优化。

    2
  • 东方奇骥
    这里注册中心信息是保存在本地文件中,如果保存在数据库,就要用数据库锁,或者zookeeper、redis的分布式锁。感谢老师,工作三年了,没写过框架,这个专栏收获不小!实战篇就超值了。
    1
    5
  • 亚洲舞王.尼古拉斯赵四
    看过了这四节rpc的课程之后,再去看了看中KafkaClient及实现的源码,和本篇讲述思想都是相似的,玥哥厉害!还是思想重要,同时觉得期末测试中的状态转换图也是中间件的基本中的基本,重要中的重要的点,KafkaClient这个接口中很多方法都是基于状态字段来给予的返回。(为什么提起状态转换图我就想到了线程的状态转换~~☺️
    3
  • 任鹏斌
    代码拿下来刚消化了一部分,慢慢消化,希望能做一些扩展,一转眼课程要结束了,老师辛苦!
    3
收起评论
显示
设置
留言
13
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部