环境
- Windows 10 20H1
- Docker Desktop for Windows 2.4.0.0
- MySQL Community 8.0.22.0
- Nacos Docker Latest (Nacos 1.3.2)
背景
看到Spring Cloud Alibaba版本更新,于是就将自己的微服务架构,一整套进行了升级。
- Spring Boot 升级到了 2.3.4
- Spring Cloud 升级到 Hoxton.SR8
- Spring Cloud Alibaba 升级到 2.2.3
- Nacos升级到1.3.2
升级之后整体顺畅多了,而且解决了长久以来一直不敢使用 Spring Cloud Alibaba 2.2.1问题。
使用 Spring Cloud Alibaba 2.2.1,会导致Oauth 2 Token 验证返回的对象数据类型不对的问题。就是下面代码中,Boolean.TRUE.equals(map.get("active") 这一句验证不过的问题。主要原因是map里面的值全被转成了String类型,查了好久没有找到问题在哪。切换到Spring Cloud Alibaba 2.2.0,就不会有问题。现在升级到Spring Cloud Alibaba 2.2.3,问题就不存在了。开心!!!
publicOAuth2AuthenticationloadAuthentication(StringaccessToken) throwsAuthenticationException, InvalidTokenException { MultiValueMap<String, String>formData=newLinkedMultiValueMap<String, String>(); formData.add(tokenName, accessToken); HttpHeadersheaders=newHttpHeaders(); headers.set("Authorization", getAuthorizationHeader(clientId, clientSecret)); Map<String, Object>map=postForMap(checkTokenEndpointUrl, formData, headers); if (map.containsKey("error")) { if (logger.isDebugEnabled()) { logger.debug("check_token returned error: "+map.get("error")); } thrownewInvalidTokenException(accessToken); } // gh-838if (!Boolean.TRUE.equals(map.get("active"))) { logger.debug("check_token returned active attribute: "+map.get("active")); thrownewInvalidTokenException(accessToken); } returntokenConverter.extractAuthentication(map); }
问题
这次升级,主要问题出现在Nacos上面。
- 一方面,Nacos 1.3.1以后,使用MySQL8,需要升级数据库
- 另一方面,现在Latest的 Nacos Docker,访问外部MySQL 8 连接不上。
错误堆栈中会出现以下两个关键信息
(一)
java.sql.SQLException: Theservertimezonevaluexxxxxisunrecognizedorrepresentsmorethanonetimezone
这个错误,主要是因为时区不对,如果这个问题解决,就会出现下面的问题
(二)
Causedby: com.mysql.cj.exceptions.CJException: PublicKeyRetrievalisnotallowed
解决
Nacos 容器运行起来之后,进入到Nacos 容器控制台。
输入
~$vimconf/application.properties
在数据库连接中增加以下参数解决
// 在数据库连接中增加allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8
完整参数
···db.num=${MYSQL_DATABASE_NUM:1} db.url.0=jdbc:mysql://${MYSQL_SERVICE_HOST}:${MYSQL_SERVICE_PORT:3306}/${MYSQL_SERVICE_DB_NAME}?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8&useSSL=${MYSQL_SSL_ENABLE:false}db.url.1=jdbc:mysql://${MYSQL_SERVICE_HOST}:${MYSQL_SERVICE_PORT:3306}/${MYSQL_SERVICE_DB_NAME}?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8&useSSL=${MYSQL_SSL_ENABLE:false}db.user=${MYSQL_SERVICE_USER} db.password=${MYSQL_SERVICE_PASSWORD···
当然,这只是表现在Nacos端,并不是Nacos本身的问题。真正的解决办法还有待深入研究。
2020-12-31 更新
感谢Nacos Docker作者的快速响应。在最新版的Nacos Docker中,作者增加了一个参数 MYSQL_SERVICE_DB_PARAM,默认值为:characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true。
可以根据需要在默认参数后面增加配置,就可以解决问题
characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8
我的Docker compose 配置为
nacos: image: nacos/nacos-server:latestcontainer_name: nacosrestart: alwaysenvironment: MODE: standaloneSPRING_DATASOURCE_PLATFORM: mysqlMYSQL_SERVICE_HOST: 192.168.101.10MYSQL_SERVICE_PORT: 3306MYSQL_SERVICE_USER: nacosMYSQL_SERVICE_PASSWORD: nacosMYSQL_SERVICE_DB_NAME: nacos_configMYSQL_SERVICE_DB_PARAM: characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&allowPublicKeyRetrieval=true&serverTimezone=GMT%2B8volumes: -/D/LocalCaches/docker-volumes/nacos/datas:/home/nacos/dataports: -8848:8848