服务发现
什么是服务发现
在微服务架构中,整个系统会按职责能力划分为多个服务,通过服务之间协作来实现业务目标。这样在我们的代码 中免不了要进行服务间的远程调用,服务的消费方要调用服务的生产方,为了完成一次请求,消费方需要知道服务 生产方的网络位置(IP地址和端口号)。
我们的代码可以通过读取配置文件的方式读取服务生产方网络位置,如下:
我们通过Spring boot技术很容易实现:
创建一个spring-boot父工程
创建Service B(服务生产者)
pom.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.xu.nacos</groupId>
<artifactId>nacos-discovery</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-restful-provider</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
Service B是服务的生产方,暴露/service服务地址,实现代码如下:
1、创建Controller
@RestController
public class RestProviderController {
//暴露一个Restful接口
@GetMapping("/service")
public String service(){
return "provider invoke";
}
}
创建application.yml,内容如下:
server:
port:56010
创建Service A(服务消费者)
pom.xml如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.xu.nacos</groupId>
<artifactId>nacos-discovery</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-restful-consumer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
创建controller
@RestController
public class RestConsumerController {
@Value("${provider.address}")
private String provider;
@GetMapping("service")
public String service(){
//远程调用
RestTemplate restTemplate = new RestTemplate();
String forObject = restTemplate.getForObject("http://" + provider + "service", String.class);
return "消费成功"+forObject;
}
}
配置文件
server:
port: 56020
#配置服务提供方的ip和端口
provider:
address: 127.0.0.1:56010
以上消费方找到服务方并进行远程调用就叫服务发现
那么该如何来发现这些服务呢?服务方实例的增加对服务的发现会产生哪些问题呢?
服务发现流程
上边的例子看上去很完美,但是,仔细考虑以下,此方案对于微服务应用而言行不通。首先,微服务可能是部署在 云环境的,服务实例的网络位置或许是动态分配的。另外,每一个服务一般会有多个实例来做负载均衡,由于宕机 或升级,服务实例网络地址会经常动态改变。再者,每一个服务也可能应对临时访问压力增加新的服务节点。正如 下图所示:
基于以上的问题,服务之间如何相互发现?服务如何管理?这就是服务发现的问题了。 服务发现就是服务消费方通过服务发现中心智能发现服务提供方,从而进行远程调用的过程。 如下图:
上图中服务实例本身并不记录服务生产方的网络地址,所有服务实例内部都会包含服务发现客户端。
(1)在每个服务启动时会向服务发现中心上报自己的网络位置。这样,在服务发现中心内部会形成一个服务注册 表,服务注册表是服务发现的核心部分,是包含所有服务实例的网络地址的数据库。
(2)服务发现客户端会定期从服务发现中心同步服务注册表 ,并缓存在客户端。
(3)当需要对某服务进行请求时,服务实例通过该注册表,定位目标服务网络地址。若目标服务存在多个网络地 址,则使用负载均衡算法从多个服务实例中选择出一个,然后发出请求。
总结:
在微服务环境中,由于服务运行实例的网络地址是不断动态变化的,服务实例数量的动态变化 ,因此无法 使用固定的配置文件来记录服务提供方的网络地址,必须使用动态的服务发现机制用于实现微服务间的相互感知。 各服务实例会上报自己的网络地址,这样服务中心就形成了一个完整的服务注册表,各服务实例会通过服务发现中 心来获取访问目标服务的网络地址,从而实现服务发现的机制。