前面我们学习了Kubernetes Ingress,是Kubernetes中的一种资源对象,用于管理集群内服务的入口流量。在Kubernetes中,可以使用Ingress来将外部流量路由到Kubernetes集群中的服务。而Nacos是一个开源的服务发现和配置管理平台,能够帮助开发人员实现动态服务发现、配置管理、服务路由等功能。
Nacos可以作为服务发现和配置管理平台,为Ingress提供服务注册和发现的功能。具体来说,Kubernetes中的Ingress Controller可以通过Nacos服务注册中心来发现服务,并将流量路由到对应的服务中。因此,Kubernetes Ingress和Nacos可以结合使用,实现更加灵活和可靠的服务管理和流量控制
Nacos致力于帮助您发现、配置和管理微服务。Nacos提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos帮助您更敏捷和容易地构建、交付和管理微服务平台。Nacos是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
在接下里的教程中,将使用Nacos作为微服务架构中的注册中心(替代:eurekba、consul等传统方案)以及配置中心(spring cloud config)来使用。
Nacos下载地址:https://github.com/alibaba/nacos/releases 本文版本:2.1.0
下载完成之后,解压。根据不同平台,执行不同命令,启动单机版Nacos服务(startup.sh脚本位于Nacos解压后的bin目录下):
Linux/Unix/Mac:sh startup.sh -m standalone
Windows: startup.cmd -m standalone
启动完成之后,访问:http://127.0.0.1:8848/nacos/,可以进入Nacos的服务管理页面(默认用户名密码为:nacos),具体如下:
在完成了Nacos服务的安装和启动之后,下面我们就可以编写两个应用(服务提供者与服务消费者)来验证服务的注册与发现了。
创建一个Spring Boot应用,命名为:alibaba-nacos-discovery-server。
(1)编辑pom.xml,加入必要的依赖配置:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Finchley.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>0.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<optional>true</optional>
</dependency>
</dependencies>
上述内容主要三部分:
我们可以去Github上看详细版的:—>springboot与springcloud详细对照信息
spring-cloud-release
(2)创建应用主类,并实现一个HTTP接口:
package com.example.demospringboot;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplication
@MapperScan(value = {"com.example.demospringboot"})
public class DemoSpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(DemoSpringbootApplication.class, args);
}
@Slf4j
@RestController
static class TestController {
@GetMapping("/hello")
public String hello(@RequestParam String name) {
log.info("invoked name = " + name);
return "hello " + name;
}
}
}
内容非常简单,@SpringBootApplication定义是个Spring Boot应用;@EnableDiscoveryClient开启Spring Cloud的服务注册与发现,由于这里引入了spring-cloud-starter-alibaba-nacos-discovery模块,所以Spring Cloud Common中定义的那些与服务治理相关的接口将使用Nacos的实现。
(3)配置服务名称和Nacos地址
spring.application.name=alibaba-nacos-discovery-server
server.port=8001
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
(4)启动上面创建的应用。可以在启动时候增加–server.port=8001的形式在本机的不同端口上启动多个实例:
# java -jar .\demoSpringboot-0.0.1-SNAPSHOT.jar --server.port=8001
# java -jar .\demoSpringboot-0.0.1-SNAPSHOT.jar --server.port=8002
(5) 在启动都ok之后,我们可以访问Nacos的管理页面http://127.0.0.1:8848/nacos/来查看服务列表,此时可以看到如下内容:
(1)创建应用主类,并实现一个HTTP接口,在该接口中调用服务提供方的接口;
客户端使用restTemplate调用服务端,其中服务端使用loadBalancerClient负载均衡
package com.example.demospringboot;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplication
@MapperScan(value = {"com.example.demospringboot"})
public class DemoSpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(DemoSpringbootApplication.class, args);
}
@Slf4j
@RestController
static class TestController {
@Autowired
LoadBalancerClient loadBalancerClient;
@GetMapping("/test")
public String test() {
// 通过spring cloud common中的负载均衡接口选取服务提供节点实现接口调用
ServiceInstance serviceInstance = loadBalancerClient.choose("alibaba-nacos-discovery-server");
String url = serviceInstance.getUri() + "/hello?name=Jacky";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(url, String.class);
return "Invoke : " + url + ", return : " + result;
}
}
}
这里使用了Spring Cloud Common中的LoadBalancerClient接口来挑选服务实例信息。然后从挑选出的实例信息中获取可访问的URI,拼接上服务提供方的接口规则来发起调用。
(2)配置服务名称和Nacos地址,让服务消费者可以发现上面已经注册到Nacos的服务。
spring.application.name=alibaba-nacos-discovery-client-common
server.port=9000
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
(3)在启动都ok之后,我们可以访问Nacos的管理页面http://127.0.0.1:8848/nacos/来查看服务列表,此时可以看到如下内容:
查看详情:
通过curl或者postman等工具发起访问,下面以curl为例:
可以看到,两次不同请求的时候,真正实际调用的服务提供者实例是不同的,也就是说,通过LoadBalancerClient接口在获取服务实例的时候,已经实现了对服务提供方实例的负载均衡。
(1)创建配置:进入Nacos的控制页面,在配置列表功能页面中,点击右上角的“+”按钮,进入“新建配置”页面,如下图填写内容:
Data ID:填入alibaba-nacos-discovery-client-common.properties
Group:不修改,使用默认值DEFAULT_GROUP
配置格式:选择Properties
配置内容:应用要加载的配置内容,这里仅作为示例,做简单配置,比如:myspace.title=Mike
(2)创建应用:编辑pom.xml,加入必要的依赖配置,比如:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
dependencies:当前应用要使用的依赖内容。这里主要新加入了Nacos的配置客户端模块:spring-cloud-starter-alibaba-nacos-config。由于在dependencyManagement中已经引入了版本,所以这里就不用指定具体版本了。
(3)修改应用主类,并实现一个HTTP接口:
package com.example.demospringboot;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@EnableDiscoveryClient
@SpringBootApplication
@MapperScan(value = {"com.example.demospringboot"})
public class DemoSpringbootApplication {
public static void main(String[] args) {
SpringApplication.run(DemoSpringbootApplication.class, args);
}
@Slf4j
@RestController
@RefreshScope
static class TestController {
@Value("${myspace.title:}")
private String title;
@Autowired
LoadBalancerClient loadBalancerClient;
@GetMapping("/test")
public String test() {
// 通过spring cloud common中的负载均衡接口选取服务提供节点实现接口调用
ServiceInstance serviceInstance = loadBalancerClient.choose("alibaba-nacos-discovery-server");
String url = serviceInstance.getUri() + "/hello?name=" + title;
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(url, String.class);
return "Invoke : " + url + ", return : " + result;
}
}
}
内容非常简单,其中通过@Value注解,注入了key为myspace.title的配置(默认为空字符串)。另外,这里还有一个比较重要的注解@RefreshScope,主要用来让这个类下的配置内容支持动态刷新,也就是当我们的应用启动之后,修改了Nacos中的配置内容之后,这里也会马上生效。
(4)创建配置文件bootstrap.properties,并配置服务名称和Nacos地址
spring.application.name=alibaba-nacos-discovery-client-common
server.port=9000
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
注意:这里必须使用bootstrap.properties。同时,spring.application.name值必须与上一阶段Nacos中创建的配置Data Id匹配(除了.properties或者.yaml后缀)。
(5)启动上面创建的应用。
INFO 16636 --- [ main] o.s.c.a.n.c.NacosPropertySourceBuilder : Loading nacos data, dataId: 'alibaba-nacos-discovery-client-common.properties', group: 'DEFAULT_GROUP'
INFO 16636 --- [ main] b.c.PropertySourceBootstrapConfiguration : Located property source: CompositePropertySource {name='NACOS', propertySources=[NacosPropertySource {name='alibaba-nacos-discovery-client-common.properties'}]}
在启动的时候,我们可以看到类似上面的日志信息,这里会输出应用程序要从Nacos中获取配置的dataId和group。如果在启动之后,发现配置信息没有获取到的时候,可以先从这里着手,看看配置加载的目标是否正确。
然后,再通过Nacos页面,修改这个内容,点击发布之后,再访问接口,可以看到返回结果变了。
同时,在应用的客户端,我们还能看到如下日志:
INFO 16636 --- [-127.0.0.1_8848] o.s.c.e.event.RefreshEventListener : Refresh keys changed: [myspace.title]
在搭建Nacos集群之前,我们需要先修改Nacos的数据持久化配置为MySQL存储。默认情况下,Nacos使用嵌入式数据库实现数据的存储。如果启动多个默认配置下的Nacos节点,数据存储是存在一致性问题的。为了解决这个问题,Nacos采用了集中式存储的方式来支持集群化部署,目前只支持MySQL的存储。
(1)初始化MySQL数据库,新建名为nacos的数据库, 并执行初始化文件:nacos-mysql.sql
,该文件可以在Nacos程序包下的conf目录下获得。执行完成后可以得到对应表结构。修改conf/application.properties
文件,增加支持MySQL数据源配置,添加(目前只支持mysql)数据源的url、用户名和密码。配置样例如下:
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://localhost:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=1234
(2) 集群配置
在Nacos的conf目录下有一个cluster.conf.example,可以直接把example扩展名去掉来使用,也可以单独创建一个cluster.conf文件,然后打开将后续要部署的Nacos实例地址配置在这里。本文以在本地不同端点启动3个Nacos服务端为例,可以如下配置:
127.0.0.1:8844
127.0.0.1:8846
127.0.0.1:8848
最好使用真实ip,避免后面容器访问的问题。
(3)高可用模式启动 Nacos:本地测试复制了三分nacos,修改conf文件夹中的application.properties文件端口号为8844,8846,8848,然后分别启动.\startup.cmd
。之后任选一个端口登录查看Nacos集群信息:
(4)Proxy配置
在Nacos的集群启动完毕之后,我们还需要提供一个统一的入口给我们用来维护以及给Spring Cloud应用访问。简单地说,就是我们需要为上面启动的的三个Nacos实例做一个可以为它们实现负载均衡的访问点。这个实现的方式非常多,这里就举个用Nginx来实现的简单例子, 通过docker启动:
docker run -d -p 8080:80 --name nginx -v F:\docker\nginx.conf:/etc/nginx/nginx.conf nginx
本地的nginx配置文件如下,配置upstream
和location /nacos/
字段实现负载均衡:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
# 配置所有nacos的实例地址
upstream nacosserver {
server 10.173.92.1:8844;
server 10.173.92.1:8846 weight=2;
server 10.173.92.1:8848 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name localhost;
# 定义/nacos代理,对应上面的upstream配置,实现负载均衡
location /nacos/ {
proxy_pass http://nacosserver/nacos/;
}
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
}
到这里,Nacos的集群搭建就完成了!我们可以通过Nginx配置的代理地址:http://localhost:8080/nacos/
来访问Nacos;
在Spring Cloud应用中也可以用这个地址来作为注册中心和配置中心的访问地址来配置:spring.cloud.nacos.discovery.server-addr=localhost:8080
;
即使关闭某个nacos实例,Nacos集群也还能正常服务。
注:
1,在Nacos使用的Tomcat版本中不支持_符号出现在域名位置,所以上面截图给出的upstream的名称是nacosserver,去掉了_符号。
2,将proxy_pass localhost:8080”中的本地主机更改为“×.×.×.×”(本机中的IPv4),否则在nginx容器访问接口的时候,去做一些权限的校验会有问题
参考:https://www.didispace.com/spring-cloud/spring-cloud-alibaba-1.html