一个体面的程序员从处理好空指针做起

故事是这样的,最近我开发了一个java服务,小伙伴开发了一个python服务,我们的服务都注册到Nacos。(Nacos是一个服务注册和发现中间件,注册到Nacos的服务通过服务名字就可以互相调用了,彼此不需要知晓对方服务所在的IP和端口)。服务调用的代码大概是这样的:

@FeignClient(name = "execute-code-service")
public interface ExecuteTestCodeClient {
    @PostMapping("/api/v1/execute/code")
    ExecuteCodeResponse executeCode(@RequestBody ExecuteCodeRequest request);
}

execute-code-service就是我的小伙伴的服务名。
昨天下午,小伙伴开心的告诉我说:“我的服务已经测试OK了,并且注册到了Nacos”。并且附上了两张截图,看上去那么完美。

于是,我开始测试了。

和之前无数次的联调一样,这次依然没那么顺。
按钮一点,一个空指针出现了。

各种debug,分析源码,发现空指针出现在服务发现组件的com.alibaba.cloud.nacos.ribbon.NacosServerIntrospector类:

    public boolean isSecure(Server server) {
        return server instanceof NacosServer ? Boolean.valueOf((String)((NacosServer)server).getMetadata().get("secure")) : super.isSecure(server);
    }

((NacosServer)server).getMetadata()获取到的结果是null, 所以空指针了。

为何我的java服务调用别的java服务不会出问题,调用python服务就出问题了?(潜意识在甩锅)

对比下Nacos中心java服务和python服务的元数据:
Java服务元数据
Python服务元数据
Nacos里注册的python服务空白的metadata是那么的显眼。
python服务空白的metadata为何是null呢?看看python服务注册nacos的代码,

def add_naming_instance(self, ..., metadata=None,...)

    def _build_metadata(self, metadata, params):
        if metadata:
            if isinstance(metadata, dict):
                params["metadata"] = json.dumps(metadata)
            else:
                params["metadata"] = metadata

很显然,如果注册时候没有传递metadata, 默认是None, 后续的_build_metadata方法也没有对metadata为None的情况进行处理。

可以说,是Java服务(ribbon)的服务发现机制和Python服务的服务注册机制共同的缺陷导致了这个bug。

那么,问题如何修改呢?
方案1:
服务发现方:(NacosServer)server).getMetadata()增加空值判断;
方案2:
服务注册方:metadata赋默认值,metadata=None修改为metadata={}
方案3:
Java服务配置ribbon的IsSecure参数,让服务发现流程跳过问题代码。

ribbon:
  IsSecure: false

问题解决了,我们不妨多想想,为什么会发生这个bug?

本质还是服务提供方和服务调用方对于空值处理都不太规范。

看看阿里出品的《Java开发手册》里是怎么说的:
阿里规范
联想到出现bug的代码可能就是阿里的开发人员写的(Nacos是阿里出品的中间件),真是有点小讽刺。

见贤思齐,见不贤而内自省之。还是要多学习别人的长处,做好自己的项目。太多的线上bug来自这些看似低级的空指针问题,作为一个体面的程序员,从处理好空指针做起吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值