Nacos搭建流程 顶
- 2019 年 12 月 16 日
- 筆記
要使用nacos,我们首先得下载它的服务端,下载地址https://github.com/alibaba/nacos/releases
根据你的Spring Cloud Alibaba版本来下载需要使用的版本

我这里是tar.gz的,下载完成后,解压,进入bin目录
执行sh startup.sh -m standalone
通过docker安装nacos服务端
docker pull nacos/nacos-server:1.1.3
docker run -d –name nacos -p 8848:8848 –env MODE=standalone nacos/nacos-server:1.1.3
然后通过浏览器访问http://127.0.0.1:8848/nacos/
此时界面如图所示

输入账号nacos,密码nacos后,进入管理界面

搭建一个Spring Cloud Alibaba项目,在父项目中,Springboot版本2.1.7,SpringCloud版本Greenwich.SR2,SpringCloudAlibaba版本2.1.1.RELEASE
<spring-cloud.version>Greenwich.SR2</spring-cloud.version> <spring-cloud-alibaba.version>2.1.1.RELEASE</spring-cloud-alibaba.version>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
在具体的子项目中放入如下依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency>
添加配置
spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848 application: name: user
启动项目,端口8080,在管理界面中可以看到

我们的项目已经被注册进来了。现在我们来建一个类似的项目,端口号8081,编写一个测试Controller,来查找之前的user项目。
@RestController public class TestController { /** * 无论使用哪种注册中心(Eureka,Zookeeper,Consul),该DiscoveryClient是通用的 * 它是一个接口 */ @Autowired private DiscoveryClient discoveryClient; @GetMapping("/test") public List<ServiceInstance> findUser() { return discoveryClient.getInstances("user"); } }
运行后,访问如下

如果user启动多个实例,这里也可以获取多个user的信息

现在我们在user模块中增加一个Controller,用另外一个模块使用RestTemplate来调用这个Controller.
@RestController public class TestController { @GetMapping("/find") public String findStr() { return "春秋一统"; } }
在调用模块中使用RestTemplate来调用,我们之前发现在discoveryClient.getInstances("user")返回List中有一个uri的属性是我们需要的,我们再拼接上/find就是我们需要的Rest API。
@Slf4j @Service public class ConnectServer { @Autowired private DiscoveryClient discoveryClient; private RestTemplate restTemplate = new RestTemplate(); @PostConstruct public void trace() { List<ServiceInstance> instances = discoveryClient.getInstances("user"); String targetUrl = instances.stream().map(instance -> instance.getUri().toString() + "/find") .findFirst() .orElseThrow(() -> new RuntimeException("当前没有实例")); String result = restTemplate.getForObject(targetUrl, String.class); log.info(result); } }
运行结果(部分日志)
2019-12-06 23:09:12.764 INFO 847 — [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 563 ms 2019-12-06 23:09:18.229 INFO 847 — [ main] c.cgc.cloud.nacos.service.ConnectServer : 春秋一统 2019-12-06 23:09:18.235 WARN 847 — [ main] c.n.c.sources.URLConfigurationSource : No URLs will be polled as dynamic configuration sources.
现在我们要整合Ribbon来负载均衡
先在调用模块加入我们需要的Apache HTTPClient依赖
<dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency>
给RestTemplate增加连接池,连接次数和超时时间。再打上Ribbon特有的标签@LoadBalanced
@Configuration public class RestTemplateConfig { @LoadBalanced @Bean public RestTemplate restTemplate() { PoolingHttpClientConnectionManager pollingConnectionManager = new PoolingHttpClientConnectionManager(); //连接池最大连接数 pollingConnectionManager.setMaxTotal(400); pollingConnectionManager.setDefaultMaxPerRoute(200); HttpClientBuilder httpClientBuilder = HttpClients.custom(); httpClientBuilder.setConnectionManager(pollingConnectionManager); //连接次数 httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)); HttpClient httpClient = httpClientBuilder.build(); HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory( httpClient); // 超时时间 clientHttpRequestFactory.setConnectTimeout(5000); clientHttpRequestFactory.setReadTimeout(5000); clientHttpRequestFactory.setConnectionRequestTimeout(5000); RestTemplate restTemplate = new RestTemplate(); restTemplate.setRequestFactory(clientHttpRequestFactory); restTemplate.setErrorHandler(new DefaultResponseErrorHandler()); return restTemplate; } }
为了以示区别,我们在user模块中修改第二个实例的返回字符串
@RestController public class TestController { @GetMapping("/find") public String findStr() { return "战国一统"; } }
在调用模块中增加测试Controller
@RestController public class BalanceController { @Autowired private RestTemplate restTemplate; @GetMapping("/trace") public String trace() { return restTemplate.getForObject("http://user/find", String.class); } }
启动调用模块


我们不断的点击刷新,它就会不断的出现春秋一统和战国一统返回字符串。
Nacos的环境配置

我们可以在命名空间中设置我们不同环境(比如开发,测试,线上等等)的配置,它们是相互隔离的,互不影响。
在项目中配置如下,加入我们现在要把项目配置到开发环境中
spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848 namespace: 9257bc96-8af7-4737-9ce1-a63da2ba2af7 application: name: user
这里需要注意的就是,我们在填写namespace的时候一定要配置它的命名空间ID,而不能配它的名称,比如dev。
项目启动后,我们可以看到我们的服务现在是在dev的服务列表中.

我们还可以配置它到集群中心
spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848 namespace: 9257bc96-8af7-4737-9ce1-a63da2ba2af7 cluster-name: GuangZhou application: name: user
启动后,点击详情,可以看到

Nacos配置中心
pom
在子项目中添加依赖
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
增加bootstrap.yml,添加如下配置(我这里是将tomcat改成了undertow,关于此处说明可以参考Feign HTTP连接的几点建议 )
Spring: cloud: nacos: discovery: server-addr: 127.0.0.1:8848 # namespace: 9257bc96-8af7-4737-9ce1-a63da2ba2af7 # cluster-name: GuangZhou config: server-addr: 127.0.0.1:8848 file-extension: yaml application: name: user profiles: active: dev server: port: 8082 undertow: # 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程 # 不要设置过大,如果过大,启动项目会报错:打开文件数过多 io-threads: 16 # 阻塞任务线程池, 当执行类似servlet请求阻塞IO操作, undertow会从这个线程池中取得线程 # 它的值设置取决于系统线程执行任务的阻塞系数,默认值是IO线程数*8 worker-threads: 256 # 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理 # 每块buffer的空间大小,越小的空间被利用越充分,不要设置太大,以免影响其他应用,合适即可 buffer-size: 1024 # 是否分配的直接内存(NIO直接分配的堆外内存) direct-buffers: true
在nacos服务台中进行如下操作

点+号,进入如下界面

然后填入数据

Data ID这里需要将Springboot的项目名称与开发环境名称用"-"连接用.yaml后缀名结尾,配置格式选择yaml,配置内容可以放入你对数据库连接,zipkin,mq,mybatis等等各种配置。
点发布返回后,就可以看到该配置列表

启动Springboot项目,从日志可以看到它会先把配置文件给拉取下来
2019-12-09 14:19:29.242 INFO [user,,,] 2129 — [ main] c.a.c.n.c.NacosPropertySourceBuilder : Loading nacos data, dataId: 'user-dev.yaml', group: 'DEFAULT_GROUP', data: logging: level: root: info com.cloud: debug file: logs/${spring.application.name}.log spring: zipkin: base-url: http://192.168.1.219:9411 enabled: true sender: type: web sleuth: sampler: probability: 1.0
生产环境的集群改造
nacos本身是使用derby来做数据持久化的,具体查看derby数据方式如下。
关闭nacos
sh shutdown.sh
使用IDEA来连接nacos,打开database工具,点+号

选择Derby(Embedded)

如果没有驱动的话,需要先下载驱动。

找到nacos安装目录/data/derby-data,使用用户名nacos,密码nacos,点Test Connection按钮,出现Successful,表示连接成功。
此后可以看到包含这样一些表的数据库

点开CONFIG_INFO表可以看到我们之前配置中心的配置信息

考虑到Derby的单节点性,生产环境需使用MySQL作为后端存储,因此需要搭建MySQL。生产中,MySQL建议至少主备模式,高可用MySQL更佳。关于高可用的mysql集群可以参考CentOS 7 Galera Cluster安装全攻略 ,主从的可以参考Docker安装mysql8主从结构 版本选择5.7就好。
生产环境部署架构图

这里5.7和8.0就在于他们的驱动不同。8.0的驱动下载地址为https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.16/mysql-connector-java-8.0.16.jar