seata: endpoint format should like ip:port

springcloud 集成 seata1.3.0 报错endpoint format should like ip:port。
不瞒各位说,搞了我一下午。

1. 错误日志

2021-03-02 16:22:09.693 ERROR 8384 --- [           main] i.s.c.r.netty.NettyClientChannelManager  : Failed to get available servers: endpoint format should like ip:port

java.lang.IllegalArgumentException: endpoint format should like ip:port
	at io.seata.discovery.registry.FileRegistryServiceImpl.lookup(FileRegistryServiceImpl.java:95) ~[seata-all-1.3.0.jar:1.3.0]
	at io.seata.core.rpc.netty.NettyClientChannelManager.getAvailServerList(NettyClientChannelManager.java:217) ~[seata-all-1.3.0.jar:1.3.0]
	at io.seata.core.rpc.netty.NettyClientChannelManager.reconnect(NettyClientChannelManager.java:162) ~[seata-all-1.3.0.jar:1.3.0]
	at io.seata.core.rpc.netty.RmNettyRemotingClient.registerResource(RmNettyRemotingClient.java:181) [seata-all-1.3.0.jar:1.3.0]
	at io.seata.rm.AbstractResourceManager.registerResource(AbstractResourceManager.java:121) [seata-all-1.3.0.jar:1.3.0]
	at io.seata.rm.datasource.DataSourceManager.registerResource(DataSourceManager.java:146) [seata-all-1.3.0.jar:1.3.0]
	at io.seata.rm.DefaultResourceManager.registerResource(DefaultResourceManager.java:114) [seata-all-1.3.0.jar:1.3.0]
	at io.seata.rm.datasource.DataSourceProxy.init(DataSourceProxy.java:99) [seata-all-1.3.0.jar:1.3.0]
	at io.seata.rm.datasource.DataSourceProxy.<init>(DataSourceProxy.java:85) [seata-all-1.3.0.jar:1.3.0]
	at io.seata.rm.datasource.DataSourceProxy.<init>(DataSourceProxy.java:74) [seata-all-1.3.0.jar:1.3.0]
	at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) ~[na:1.8.0_161]
	at io.seata.spring.annotation.datasource.DataSourceProxyHolder.putDataSource(DataSourceProxyHolder.java:64) ~[seata-all-1.3.0.jar:1.3.0]
	at io.seata.spring.annotation.datasource.SeataAutoDataSourceProxyAdvice.invoke(SeataAutoDataSourceProxyAdvice.java:34) ~[seata-all-1.3.0.jar:1.3.0]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) ~[spring-aop-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) ~[spring-aop-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at com.zaxxer.hikari.HikariDataSource$$EnhancerBySpringCGLIB$$8d3db51d.isRegisterMbeans(<generated>) ~[HikariCP-3.4.5.jar:na]
	at org.springframework.boot.autoconfigure.jdbc.DataSourceJmxConfiguration$Hikari.validateMBeans(DataSourceJmxConfiguration.java:66) ~[spring-boot-autoconfigure-2.2.13.RELEASE.jar:2.2.13.RELEASE]
	at org.springframework.boot.autoconfigure.jdbc.DataSourceJmxConfiguration$Hikari.<init>(DataSourceJmxConfiguration.java:61) ~[spring-boot-autoconfigure-2.2.13.RELEASE.jar:2.2.13.RELEASE]
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_161]
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_161]
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_161]
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_161]
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:204) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:310) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:295) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1203) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897) ~[spring-beans-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.12.RELEASE.jar:5.2.12.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141) ~[spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) ~[spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:405) ~[spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1215) ~[spring-boot-2.2.13.RELEASE.jar:2.2.13.RELEASE]
	at com.seven.mall.order.OrderApplication.main(OrderApplication.java:12) ~[classes/:na]

2. 解决方案

file.conf 中添加如下配置:
是不是跟其他博客一样呢?别着急关,有一点不一样。我这里的是vgroupMapping,不是vgroup_mapping

service {
  #vgroup->rgroup
  vgroupMapping.order-service-seata-service-group = "default"
  #only support single node
  default.grouplist = "127.0.0.1:8091"
  #degrade current not support
  enableDegrade = false
  #disable
  disable = false
  #unit ms,s,m,h,d represents milliseconds, seconds, minutes, hours, days, default permanent
  max.commit.retry.timeout = "-1"
  max.rollback.retry.timeout = "-1"
}

对了,默认下载的是没有 service 这个配置的,我是在官方文档中找的,给你们链接 https://github.com/seata/seata-samples/blob/master/doc/quick-integration-with-spring-cloud.md

2.1 补充

启动多个项目时还是可能有问题,需要统一指定 tx-service-group ,根据官方文档,可以通过 application.yml 中添加如下配置

spring:
  cloud:
    alibaba:
      seata:
        tx-service-group: seven-seata-service-group

每个项目中都需要做这个配置,注意file.conf中的vgroupMapping.seven-seata-service-group也需要跟yml中一样。然后把 file.confregistry.conf 一模一样的复制到需要控制统一事务的微服务中就可以了。

3. 吐槽

气死我了 [○・`Д´・ ○] ,seata官方文档都是0.x的,1.x的文档都没看到,1.x后把配置名称改成了vgroupMapping 驼峰命名,这么致命的问题,怎么通过 code review 的。。。

4. 解决的方法 - 看源码

不得已,网上也没有解决方案,只能撕开看源码了。
通过报错的第一行,点进去 FileRegistryServiceImpl.java:95

at io.seata.discovery.registry.FileRegistryServiceImpl.lookup(FileRegistryServiceImpl.java:95) ~[seata-all-1.3.0.jar:1.3.0]

找到抛异常的那一行,逐行往上分析,我在下面代码中写了注释

@Override
public List<InetSocketAddress> lookup(String key) throws Exception {
	// clusterName 是通过这个key去找的,使用debug模式查看到key的值是"order-service-seata-service-group"
	// 看名字不像是我定义的,但是 order-service 是我的服务名,后面的盲猜是seata默认的后缀
	// 官方文档居然说是 ${spring.application.name}-fescar-service-group 可恶。。。
	// 点进下面这个方法 getServiceGroup(key)
    String clusterName = getServiceGroup(key);
    if (clusterName == null) {
        return null;
    }
    String endpointStr = CONFIG.getConfig(
    	// 点进去每个常量查看value,组合起来就是 "service. " + clusterName + " .grouplist"
        PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + clusterName + POSTFIX_GROUPLIST);
    if (StringUtils.isNullOrEmpty(endpointStr)) {
        throw new IllegalArgumentException(clusterName + POSTFIX_GROUPLIST + " is required");
    }
    String[] endpoints = endpointStr.split(ENDPOINT_SPLIT_CHAR);
    List<InetSocketAddress> inetSocketAddresses = new ArrayList<>();
    for (String endpoint : endpoints) {
        String[] ipAndPort = endpoint.split(IP_PORT_SPLIT_CHAR);
        if (ipAndPort.length != 2) {
        	// 这里抛的异常,往上面看 ↑↑↑↑↑↑↑
            throw new IllegalArgumentException("endpoint format should like ip:port");
        }
        inetSocketAddresses.add(new InetSocketAddress(ipAndPort[0], Integer.parseInt(ipAndPort[1])));
    }
    return inetSocketAddresses;
}

点进方法 getServiceGroup(key)

/**
 * Get current service group name
 *
 * @param key service group
 * @return the service group name
 */
default String getServiceGroup(String key) {
	// 通过常量组合后的key是: service.vgroupMapping.order-service-seata-service-group
    key = PREFIX_SERVICE_ROOT + CONFIG_SPLIT_CHAR + PREFIX_SERVICE_MAPPING + key;
    if (!SERVICE_GROUP_NAME.contains(key)) {
        ConfigurationCache.addConfigListener(key);
        SERVICE_GROUP_NAME.add(key);
    }
    return ConfigurationFactory.getInstance().getConfig(key);
}

好家伙,这不是跟我配置在 file.conf中的 vgroup_mapping.order-service-seata-service-group = "default" 长的差不多吗,对比出来,才知道 vgroup_mapping 改成 vgroupMapping 了了了了了了了了了 [○・`Д´・ ○]。
算了,不气。

最起码看了一遍源码,知道了他是通过定义的 service.vgroupMapping.order-service-seata-service-group 找到配置的值是 default,然后通过 default.grouplist 找到配置的值是 127.0.0.1:8091 也就是seata-server的地址。

真的是,好家伙,这个alibaba也有这么不靠谱的时候,文档都不按版本出,头发都少了一把。

5. seata1.3.0 百度网盘下载

我另一篇中有下载地址 https://blog.csdn.net/u012371450/article/details/114180571?spm=1001.2014.3001.5501


6. 补充

如果你跟我一样,把seata-server部署在另一台机器上,可能会出现 can not connect to services-server.

io.seata.common.exception.FrameworkException: can not connect to services-server.
	at io.seata.core.rpc.netty.NettyClientBootstrap.getNewChannel(NettyClientBootstrap.java:182) ~[seata-all-1.3.0.jar:1.3.0]
	at io.seata.core.rpc.netty.NettyPoolableFactory.makeObject(NettyPoolableFactory.java:58) ~[seata-all-1.3.0.jar:1.3.0]
	at io.seata.core.rpc.netty.NettyPoolableFactory.makeObject(NettyPoolableFactory.java:34) ~[seata-all-1.3.0.jar:1.3.0]
	at org.apache.commons.pool.impl.GenericKeyedObjectPool.borrowObject(GenericKeyedObjectPool.java:1220) ~[commons-pool-1.6.jar:1.6]
	at io.seata.core.rpc.netty.NettyClientChannelManager.doConnect(NettyClientChannelManager.java:206) [seata-all-1.3.0.jar:1.3.0]
	at io.seata.core.rpc.netty.NettyClientChannelManager.acquireChannel(NettyClientChannelManager.java:103) [seata-all-1.3.0.jar:1.3.0]
	at io.seata.core.rpc.netty.NettyClientChannelManager.reconnect(NettyClientChannelManager.java:175) [seata-all-1.3.0.jar:1.3.0]
	at io.seata.core.rpc.netty.RmNettyRemotingClient.registerResource(RmNettyRemotingClient.java:181) [seata-all-1.3.0.jar:1.3.0]
	at io.seata.rm.AbstractResourceManager.registerResource(AbstractResourceManager.java:121) [seata-all-1.3.0.jar:1.3.0]
	at io.seata.rm.datasource.DataSourceManager.registerResource(DataSourceManager.java:146) [seata-all-1.3.0.jar:1.3.0]

同样通过debug源码,发现我配置的 default.grouplist = "192.168.7.254:8091" 并没有生效,他读取的还是默认的127.0.0.1:8091

后来通过修改 default 解决

  vgroupMapping.gulimall-seata-service-group = "my_seata"
  my_seata.grouplist = "192.168.7.254:8091"

就是把 default 改成了自定义的名字,不知道这里为什么配置default的时候不读取我的配置,后来就没有去深究了,后面有时间再看吧。有知道这个问题的同学,欢迎指教!!!

  • 36
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值