转载

从一次解决开发环境问题聊聊为什么要看源码

去年写了Dubbo源码解析系列,但是因为一些不可抗拒的因素(加班),导致通信、编解码部分还没写.同时在和很多朋友交流过程中,其中反馈最多的一个问题是.看源码到底有什么用?究竟是不是真的只是面试时装装逼,装完继续CRUD.

其实之所以有这样的疑问,主要是因为平时遇到的问题都能通过搜索引擎解决.然而,我近两年的做的都是基础平台相关的工作,还是经常遇到一些必须要看源码才能解决的问题.所以我觉得光把自己看源码的经验分享出来还不够,更重要是讲清楚,看源码,究竟解决了什么实际问题.

本篇是 为什么要看源码系列 的第三篇.先交代一下背景

由于公司做的是海外业务,为了方便海外同事办公.我们把公司的开发服务器(以下简称sit环境)迁移到了海外.但是这样就产生了一个问题.由于服务器在海外,运维部表示由于政策原因(具体细节不透露),那么我们将无法访问到sit环境.既然无法访问,那么这个sit环境对于我们就形同虚设了.经过协调.运维用Nginx做端口转发.把我们常用的中间件(zookeeper,RocketMQ)、数据库地址做映射.但是这样依然存在一些问题,下面画图分析

类比学习,浅析常见中间件原理

其实我们常见的中间件的原理都大致相同,你了解一种后,通过类比学习.很容易掌握其他的.下面拿RocketMQ举例.演示一下什么叫类比学习法

RocketMQ的官方文档中物理部署结构图如下:

从一次解决开发环境问题聊聊为什么要看源码

NameSever 你可能不知道是什么.其实这个是RocketMQ3.X版本引入的,之前用的是zookeeper.就是说,3.X版本发现zookeeper功能很强大, 但是人家其实用不到zookeeper这么多功能,基本上只用到了zookeeper的分布式协调,也就是注册中心的功能,就弄了个更轻量的 NameSever .

那么 Broker 是什么呢? 这个是数据存储的核心,也是真正的MQ服务器.我们所谓的消息存储,接收,拉取,推送操作都是在这个broker进行的.

简单的说,我们平时在项目中配置的mq地址是 NameSever .然后 Broker 把信息注册到 NameSever .在框架的底层,我们访问 NameSever 的时候,它通过注册的信息真正发起网络请求去访问注册的 Broker .

类比fastDFS学习

那么接下来我们就类比一下 fastDFS

从一次解决开发环境问题聊聊为什么要看源码
从一次解决开发环境问题聊聊为什么要看源码

从上面两个图你就可以看出.在 fastDFS 中, Tracker Server 就类似 NameSever , Storage Server 就类似 Broker .原理基本是一样的.同样的,平时我们项目中配置的地址其实是 Tracker Server 的地址

类比Dubbo学习

Dubbo的原理我这里就不想再多做解释了,之前已经从源码角度各种剖析了.这里给之前没看过我Dubbo源码解析的朋友简单科普一下(真的只是简单讲两句)

两个Dubbo服务之间的调用,绝大多数情况是网络调用(为什么是绝大多数.因为这个涉及到本地暴露和远程暴露的问题).那么网络调用,至少要确定三个参数.就是

url地址
请求参数
响应参数

所以Dubbo最简单的原理就是,生产者把本机的ip地址和暴露的接口信息在zookeeper上创建节点.因为本机的ip地址就可以确定请求的url地址,接口信息可以确定请求和响应的参数.然后消费者调用接口的时候,被动态代理拦截到,然后通过网络请求调用提供者.

同样的,我们在项目中配置的地址是zookeeper的地址.原因同上两个中间件原理一致

你会发现,中间件的简单原理基本是一样的.通过这个类比学习,你以后遇到其他的中间件,哪怕是自己公司自研的中间件,他们的原理你也能迅速上手.

遇到的问题

分析完原理之后,那我们遇到了什么问题呢?比如RocketMQ,我们配置的是 NameSever 的地址,那么这个地址我们可以通过Nginx映射出来.这样我们就可以访问到 NameSever .但是 Broker 的地址,是Rocket自己注册上去的.我们即使映射了 192.168.X.XXX .但是 Broker 注册地址的逻辑代码里面还是会把 192.168.Y.YYY 注册上去.那么我们访问的还是 192.168.Y.YYY 那么我们映射的这个 192.168.X.XXX 就没有作用.

那么我们是不是装个逼秀一波操作,改源码的逻辑,让 Broker 注册的地址按照我们映射的 192.168.X.XXX 注册上去呢?

从一次解决开发环境问题聊聊为什么要看源码

我只想说,年轻人,你这个思想很危险啊!

从一次解决开发环境问题聊聊为什么要看源码

编程讲究的是开闭原则,再说,你确定能驾驭得住的RocketMQ的源码改动吗?我都说了,遇到问题,先不要着急看源码.先看官方文档,再通过搜索引擎,如果都不能解决的.我们再看源码.我百度搜索第一条就是答案的我还看个毛线源码!那么我们来看下官方文档

从一次解决开发环境问题聊聊为什么要看源码

人家这个说得就很清楚了,默认是注册本地的ip地址上去,但是你可以设置.所以我们把自己的映射的ip地址配置上去就OK了.

Dubbo的问题

RocketMQ的问题我们通过官方文档解决了.但是Dubbo的问题文档没有.搜索了有类似答案,但是依然没有把原理讲清楚.那么我们就直入源码一探究竟(好吧,让我装个逼)

如果你之前就关注肥朝,一直有看过我的dubbo源码解析系列,比如 dubbo源码解析-zookeeper创建节点 那么你就能像我这种风一般的男子一样迅速定位到源码中获取ip地址的源码片段.如下

从一次解决开发环境问题聊聊为什么要看源码

这部分的逻辑是,先调用 InetAddress.getLocalHost().getHostAddress() ,如果该方法返回一个合法地址,就直接认为这个地址是本地的ip地址.否则会遍历本地的所有网卡,并返回找到的第一个合法地址

//这部分是jdk的api
host = InetAddress.getLocalHost().getHostAddress();
复制代码

既然是jdk的api,那么要弄懂原理就好搞很多了.我们直接看文档注释

/**
 * Returns the address of the local host. This is achieved by retrieving
 * the name of the host from the system, then resolving that name into
 * an {@code InetAddress}.
 *
 * <P>Note: The resolved address may be cached for a short period of time.
 * </P>
 *
 * <p>If there is a security manager, its
 * {@code checkConnect} method is called
 * with the local host name and {@code -1}
 * as its arguments to see if the operation is allowed.
 * If the operation is not allowed, an InetAddress representing
 * the loopback address is returned.
 *
 * @return     the address of the local host.
 *
 * @exception  UnknownHostException  if the local host name could not
 *             be resolved into an address.
 *
 * @see SecurityManager#checkConnect
 * @see java.net.InetAddress#getByName(java.lang.String)
 */
复制代码

从文档的大概意思可以看出,他获取的ip地址,和 hostName 有关.那么这样我们就有了突破口.

我们通过linux命令( uname -n )查看机器的hostName,比如

从一次解决开发环境问题聊聊为什么要看源码

然后编辑host文件

vi /etc/hosts
复制代码

比如设置

192.168.1.102 testdemo
复制代码
从一次解决开发环境问题聊聊为什么要看源码

那么我们启动dubbo服务

从一次解决开发环境问题聊聊为什么要看源码

当然这样我还是不放心,我们去zookeeper上看看节点

从一次解决开发环境问题聊聊为什么要看源码

果然和我们看到的是一样的.

从一次解决开发环境问题聊聊为什么要看源码
原文  https://juejin.im/post/5caa97486fb9a05e7b5c7c12
正文到此结束
Loading...