SpringCloud、dubbo 和 druid 问题总结

背景:

  我们当前的微服务架构采用的是 SpringCloud 全家桶 + dubbo + druid + apllo 等技术集成的。

1、多服务实例相同端口冲突问题

  目前线上服务器内容动辄 128 ~ 256GB,我们一个服务最大内存设置不超过 32GB,那么为了有效利用服务器资源,我们都会在一台服务器上启动多个服务实例。那此时如果配置文件中配置写死了一个固定的 port 就会发生 dubbo 服务端口冲突。需要将 dubbo 的端口设置为 随机端口,具体如下所示:

dubbo:
  scan:
    base-packages: com.search.bs
  protocol:
    name: dubbo
    port: -1 #20881,将原来写死的 20881 改为随机,默认端口为 20880
    serialization: hessian2

 2、mysql 加载超时问题

  链接 mysql 我们使用的是 druid 的数据库连接池,我们当前业务涉及到正排加载,而有的业务线数据量较大,且得到对应需要的正排内容加载查询的时候会很慢,导致前一个加载完成后紧接着加载第二个内容的时候,此时 mysql 链接不可用,或者当前的链接耗时太长也导致不可用状态:

druid:
    #初始化大小,最小,最大
    initial-size: 10
    max-active: 300
    min-idle: 5
    #配置获取连接等待超时的时间
    max-wait: 300000
    #检测连接是否有效的sql
    validation-query: "select '1'"
    validation-query-timeout: 2000
    #从连接池里面获取连接时都会测试连接的有效性。这个是获取一个稳定连接最简单有效的手段,前提是如果你的性能要求不是非常高
    test-on-borrow: true
    test-on-return: false
    #对已经取到的connection进行连接有效性的检测
    test-while-idle: true
    #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
    time-between-eviction-runs-millis: 60000
    #配置一个连接在池中最小生存的时间,单位是毫秒
    min-evictable-idle-time-millis: 300000
    remove-abandoned: true

 其中最重要的是将:test-on-borrow 设置为 true,因为我们只是在初始化的时候加载正排,所以无所谓性能要求。

3、服务注册回调异常

有一同事的 mac 升级为最新版本,导致最近的整个微服务架构启动不起来了,一直卡在某个错误上,先来看一段警告信息:

[2020-04-14 18:19:49,391][dev][WARN][main][] o.a.d.c.AbstractConfig -  [DUBBO] Connection refused (Connection refused), dubbo version: 2.7.3, current host: 172.18.18.95
java.net.ConnectException: Connection refused (Connection refused)
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
	at java.net.Socket.connect(Socket.java:589)
	at org.apache.dubbo.config.ServiceConfig.findConfigedHosts(ServiceConfig.java:698)
	at org.apache.dubbo.config.ServiceConfig.doExportUrlsFor1Protocol(ServiceConfig.java:560)
	at org.apache.dubbo.config.ServiceConfig.doExportUrls(ServiceConfig.java:457)
	at org.apache.dubbo.config.ServiceConfig.doExport(ServiceConfig.java:415)
	at org.apache.dubbo.config.ServiceConfig.export(ServiceConfig.java:378)
	at org.apache.dubbo.config.spring.ServiceBean.export(ServiceBean.java:336)
	at org.apache.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:114)
	at org.apache.dubbo.config.spring.ServiceBean.onApplicationEvent(ServiceBean.java:60)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:402)
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:359)
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:896)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.finishRefresh(ServletWebServerApplicationContext.java:162)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:552)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:744)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:391)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
	at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:140)
	at com.mfw.search.bs.SearchBsBootstrap.main(SearchBsBootstrap.java:23)

 此时该服务在 nacos 注册中心是已经注册成功的,但是对应的服务 ip 为:127.0.0.1,而从日志中报出来的信息当前 ip 为:172.18.18.95,从异常信息中直观的可以看到是 socke 拒绝连接,为什么会拒绝连接呢?明明 nacos 上已经注册成功了,从网上查了好多说修改 /etc/hosts,但是并没有解决这个问题,而且明明之前是好使的,周边没有升级的小伙伴使用他当前 git 分支代码启动也是一点问题都没有,这就奇怪了,难道真的是mac 电脑升级导致的吗?

  但是不管是不是升级导致的,这个问题还是需要解决的。首先我们需要明确问题的原因:

    1. 客户端向 nacos 发起请求注册成功

    2. 通过服务端回调的时候通过 127.0.0.1 无法回调回去(因为你的真实 ip 为 172.18.18.95),导致 socket 拒绝连接

  debug dubbo 代码发现,在 NetUtils 中的 getLocalAddress0 这个方法,获取到的 ip 为 localhost/127.0.0.1,而且设置完对应的 hosts 也不受影响,所以我们的想法也很简单,需要改动 dubbo 的相关配置来约束相应的 ip 地址:(只有本地环境可能会发生这种问题,线上不会存在,所以在一定程度上可以这么做)

dubbo:
  scan:
    base-packages: com.mfw.search.bs
  protocol:
    name: dubbo
    port: -1
    serialization: hessian2
    host: 172.18.18.95 #指定好当前本机 ip 地址

 相应的 spring相关配置也需要指定当前注册的服务的 ip 地址为某个段内的,可以将 127.0.0.1 屏蔽掉:

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
  application:
    name: search-bs-lyx #应用名。很重要!是注册中心的主键,gateway路由也需要靠它
  main:
    allow-bean-definition-overriding: true
  cloud:
    nacos: #采用nacos注册中心
      discovery:
        enabled: true
        register-enabled: true
        namespace: 6947fa15-b976-45f4-b121-4c05e802e8xx
        endpoint: 'nacosendpoint.mtech.svc.ab:8098'
    inetutils:
      preferred-networks: 172 #限定选择前缀为 172 的 ip

 这样就能解决以上问题,一般情况下 dubbo 是不需要指定 ip 的,但是如果不指定解决不了再指定一定会解决掉问题,这个主要就是绑定 nacos 注册的时候使用的 ip 地址

而 spring 规范的前缀 ip,这个主要是指定 nacos 注册的服务分配的 ip,具体如下图的一个服务启动在 nacos 中的服务注册情况,可以对照 dubbo 和 spring 配置的 ip 来区分对待:

猜你喜欢

转载自www.cnblogs.com/liang1101/p/12702631.html
今日推荐