## 原理 [14.user-center模块](11.user-center%E6%A8%A1%E5%9D%97.md) ## 改依赖 将eureka-client依赖替换alibaba服务发现组件 ![](https://img.kancloud.cn/5f/5e/5f5ec9bdfc91f2bb9357177053b74b5f_1907x390.png) ![](https://img.kancloud.cn/61/e4/61e44265ba2b0deb32fd11a526fe886b_1605x621.png) ``` <!-- 选用nacos时打开--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--alibaba sentinel--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> ``` ## 改配置 * eureka client与 nacos client区别 ![](https://img.kancloud.cn/f2/e9/f2e902ade981313193951b159d7fc434_1887x782.png) * 使用公共配置 ![](https://img.kancloud.cn/3a/60/3a60cca5ea27e586830282a4c1713d82_1374x646.png) * user-center配置 ![](https://img.kancloud.cn/1f/9d/1f9d9ddb2bcb8ac83a5f24bcfcba01cf_1920x522.png) * user-center.yaml ![](https://img.kancloud.cn/08/60/086099e6a0dc07d4fc893eff35a45d69_1920x517.png) ``` #端口配置 server: port: 7000 #固定端口 # port: ${randomServerPort.value[7000,7005]} #随机端口 spring: datasource: # JDBC 配置(驱动类自动从url的mysql识别,数据源类型自动识别) url: jdbc:mysql://59.110.164.254:3306/user-center?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false username: root password: root driver-class-name: com.mysql.cj.jdbc.Driver #连接池配置(通常来说,只需要修改initialSize、minIdle、maxActive initial-size: 1 max-active: 20 min-idle: 1 # 配置获取连接等待超时的时间 max-wait: 60000 #打开PSCache,并且指定每个连接上PSCache的大小 pool-prepared-statements: true max-pool-prepared-statement-per-connection-size: 20 validation-query: SELECT 'x' test-on-borrow: false test-on-return: false test-while-idle: true #配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 time-between-eviction-runs-millis: 60000 #配置一个连接在池中最小生存的时间,单位是毫秒 min-evictable-idle-time-millis: 300000 filters: stat,wall # WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter #是否启用StatFilter默认值true web-stat-filter.enabled: true web-stat-filter.url-pattern: /* web-stat-filter.exclusions: "*.js , *.gif ,*.jpg ,*.png ,*.css ,*.ico , /druid/*" web-stat-filter.session-stat-max-count: 1000 web-stat-filter.profile-enable: true # StatViewServlet配置 #展示Druid的统计信息,StatViewServlet的用途包括:1.提供监控信息展示的html页面2.提供监控信息的JSON API #是否启用StatViewServlet默认值true stat-view-servlet.enabled: true #根据配置中的url-pattern来访问内置监控页面,如果是上面的配置,内置监控页面的首页是/druid/index.html例如: #http://110.76.43.235:9000/druid/index.html #http://110.76.43.235:8080/mini-web/druid/index.html stat-view-servlet.url-pattern: /druid/* #允许清空统计数据 stat-view-servlet.reset-enable: true stat-view-servlet.login-username: admin stat-view-servlet.login-password: admin #StatViewSerlvet展示出来的监控信息比较敏感,是系统运行的内部情况,如果你需要做访问控制,可以配置allow和deny这两个参数 #deny优先于allow,如果在deny列表中,就算在allow列表中,也会被拒绝。如果allow没有配置或者为空,则允许所有访问 #配置的格式 #<IP> #或者<IP>/<SUB_NET_MASK_size>其中128.242.127.1/24 #24表示,前面24位是子网掩码,比对的时候,前面24位相同就匹配,不支持IPV6。 #stat-view-servlet.allow= #stat-view-servlet.deny=128.242.127.1/24,128.242.128.1 # Spring监控配置,说明请参考Druid Github Wiki,配置_Druid和Spring关联监控配置 #aop-patterns= # Spring监控AOP切入点,如x.y.z.service.*,配置多个英文逗号分隔 ################### mysq end ########################## # zipkin: # base-url: http://127.0.0.1:11008 redis: ################### redis 单机版 start ########################## host: 59.110.164.254 port: 6379 timeout: 6000 database: 8 lettuce: pool: max-active: 10 # 连接池最大连接数(使用负值表示没有限制),如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽) max-idle: 8 # 连接池中的最大空闲连接 ,默认值也是8 max-wait: 100 # # 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException min-idle: 2 # 连接池中的最小空闲连接 ,默认值也是0 shutdown-timeout: 100ms ################### redis 单机版 end ########################## # cluster: # nodes: 130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001 # #130.75.131.237:7000,130.75.131.238:7000,130.75.131.239:7000,130.75.131.237:7001,130.75.131.238:7001,130.75.131.239:7001 # #192.168.3.157:7000,192.168.3.158:7000,192.168.3.159:7000,192.168.3.157:7001,192.168.3.158:7001,192.168.3.159:7001 # timeout: 1000 # 连接超时时间(毫秒) # lettuce: # pool: # max-active: 10 # 连接池最大连接数(使用负值表示没有限制),如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽) # max-idle: 8 # 连接池中的最大空闲连接 ,默认值也是8 # max-wait: 100 # # 等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。如果超过等待时间,则直接抛出JedisConnectionException # min-idle: 2 # 连接池中的最小空闲连接 ,默认值也是0 # shutdown-timeout: 100ms mybatis-plus: global-config: banner: false configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl mapper-locations: classpath*:com/open/**/dao/*.xml security: oauth2: ignored: /users-anon/** , /doc.html ,/document.html ,/users/save token: store: type: redis #设置最大超时时间 ribbon: ServerListRefreshInterval: 10 #刷新服务列表源的间隔时间 OkToRetryOnAllOperations: true MaxAutoRetries: 1 MaxAutoRetriesNextServer: 1 ReadTimeout: 16000 ConnectTimeout: 16000 #设置最大容错超时时间 hystrix: command: default: execution: timeout: enabled: true isolation: thread: timeoutInMilliseconds: 16000 logging: level: com.open.capacity: INFO org.hibernate: INFO org.hibernate.type.descriptor.sql.BasicBinder: TRACE org.hibernate.type.descriptor.sql.BasicExtractor: TRACE # com.neusoft: DEBUG # com.netflix: DEBUG #用于心跳检测输出的日志 ``` * 配置中心的优先级 Spring Cloud Alibaba Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置。 1: 通过内部相关规则(应用名、扩展名 )自动生成相关的 Data Id 配置 2: 通过 spring.cloud.nacos.config.ext-config[n].data-id 的方式支持多个扩展 Data Id 的配置,多个 Data Id 同时配置时,他的优先级关系是 spring.cloud.nacos.config.ext-config[n].data-id 其中 n 的值越大,优先级越高。(2.1>2.2>2.3) 3: 通过 spring.cloud.nacos.config.shared-dataids 支持多个共享 Data Id 的配置 当三种方式共同使用时,他们的一个优先级关系是:1 > 2 >3,如图所示: ![](https://img.kancloud.cn/f0/91/f09129b7636ac1eb7e8ac2dbb1684d12_1112x585.png) ## 启动项目 ![](https://img.kancloud.cn/79/5c/795c038925def788182eabd2e5f7cead_1920x463.png) ## nacos 源码分析 ### 自动装配 ![](https://img.kancloud.cn/3b/58/3b58a43996b3771f0651ae9ea424f3ca_1739x343.png) #### 注册逻辑 * ->com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration.nacosAutoServiceRegistration(NacosServiceRegistry, AutoServiceRegistrationProperties, NacosRegistration) * -->org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration.register() * --->org.springframework.cloud.alibaba.nacos.registry.NacosServiceRegistry.register(Registration) * ---->com.alibaba.nacos.client.naming.net.NamingProxy.registerService(String, String, Instance) ``` public void registerService(String serviceName, String groupName, Instance instance) throws NacosException { NAMING_LOGGER.info("[REGISTER-SERVICE] {} registering service {} with instance: {}", namespaceId, serviceName, instance); final Map<String, String> params = new HashMap<String, String>(9); params.put(CommonParams.NAMESPACE_ID, namespaceId); params.put(CommonParams.SERVICE_NAME, serviceName); params.put(CommonParams.GROUP_NAME, groupName); params.put(CommonParams.CLUSTER_NAME, instance.getClusterName()); params.put("ip", instance.getIp()); params.put("port", String.valueOf(instance.getPort())); params.put("weight", String.valueOf(instance.getWeight())); params.put("enable", String.valueOf(instance.isEnabled())); params.put("healthy", String.valueOf(instance.isHealthy())); params.put("ephemeral", String.valueOf(instance.isEphemeral())); params.put("metadata", JSON.toJSONString(instance.getMetadata())); reqAPI(UtilAndComs.NACOS_URL_INSTANCE, params, HttpMethod.POST); } ``` #### 心跳检测 * -> java.util.concurrent.ScheduledExecutorService.schedule(Runnable, long, TimeUnit) ``` public long sendBeat(BeatInfo beatInfo) { try { if (NAMING_LOGGER.isDebugEnabled()) { NAMING_LOGGER.debug("[BEAT] {} sending beat to server: {}", namespaceId, beatInfo.toString()); } Map<String, String> params = new HashMap<String, String>(4); params.put("beat", JSON.toJSONString(beatInfo)); params.put(CommonParams.NAMESPACE_ID, namespaceId); params.put(CommonParams.SERVICE_NAME, beatInfo.getServiceName()); String result = reqAPI(UtilAndComs.NACOS_URL_BASE + "/instance/beat", params, HttpMethod.PUT); JSONObject jsonObject = JSON.parseObject(result); if (jsonObject != null) { return jsonObject.getLong("clientBeatInterval"); } } catch (Exception e) { NAMING_LOGGER.error("[CLIENT-BEAT] failed to send beat: " + JSON.toJSONString(beatInfo), e); } return 0L; } ``` #### 健康检测 * com.alibaba.cloud.nacos.endpoint.NacosDiscoveryEndpointAutoConfiguration.nacosDiscoveryHealthIndicator(NacosDiscoveryProperties) ``` public boolean serverHealthy() { try { String result = reqAPI(UtilAndComs.NACOS_URL_BASE + "/operator/metrics", new HashMap<String, String>(2)); JSONObject json = JSON.parseObject(result); String serverStatus = json.getString("status"); return "UP".equals(serverStatus); } catch (Exception e) { return false; } } ``` ## user-center 内部原理请参考03.模块详解部分