嗡汤圆的Spring Cloud自学(PART.2):eureka服务注册与代理端使用

来源:互联网 发布:if it rains it pours 编辑:程序博客网 时间:2024/04/28 04:37

前言

传统的微服务的调用一般是直接再客户端发送请求到微服务的地址和端口进行调用,或者当微服务有多个副本时,通过配置nginx反向代理进行负载均衡。
客户端直接调用:
这里写图片描述
或者nginx负载:
这里写图片描述
以上两种情况均需要手动维护微服务的应用地址和端口,不易于微服务集群维护,当微服务出错或者关闭时,可能引起服务异常。
因此,若可以让微服务在启动后自行在一个地方注册,并统一管理微服务地址则省去了手动维护服务地址的麻烦。同时统一管理平台也可以监视各个微服务的运行状态。
这里写图片描述

注册服务(eureka)

通过假设Spring-eureka-server可以方便的构建这种微服务平台。

eureka项目构建

通过start.spring.io或者maven构建即可。若使用start.spring.io,则勾选eureka-server 和 config-client 即可,POM文件省略。

在设置application.properties 中设置端口server.port=8761
在设置bootstrap.properties中设置应用名称为:eureka-server
在启动application.java入口中加入注解@EnableEurekaServer

@EnableEurekaServer@SpringBootApplicationpublic class EurekaServerApplication {    public static void main(String[] args) {        SpringApplication.run(EurekaServerApplication.class, args);    }}

启动效果

启动后,访问该项目:http://localhost:8761 即可看到eureka的服务页面,从页面中可以看见,服务列表中有一个eureka-server服务,即该项目自身。
这里写图片描述

服务注册

将上一篇博客中的reservation-service注册到eureka中,则仅需添加eureka依赖:

<dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-eureka</artifactId>        </dependency>

然后在启动代码中添加注解@EnableDiscoveryClient 即可:

@EnableDiscoveryClient@SpringBootApplicationpublic class ReservationServiceApplication {public static void main(String[] args) {        SpringApplication.run(ReservationServiceApplication.class, args);    }}

启动reservation-service项目,再刷新eureka页面,可以看见服务已注册:
这里写图片描述

代理端

代理端的作用在于代替原微服务接受请求,并将请求转发至可用的微服务中获取结果后,将结果处理并送回给客户端。
本例中的代理端将根据客户端的请求信息从eureka服务中查找可用的服务接口地址,并将请求传递下去。

代理端项目构建

在start.spring.io中勾选eureka discoveryconfig-client 即可。若需要对请求进行加工处理和监视,也可勾上zuul (边缘代理或edge proxy)组件。POM文件省略。
在Application入口中加入注解@EnableZuulProxy @EnableDiscoveryClient 即可。

@EnableZuulProxy@EnableDiscoveryClient@SpringBootApplicationpublic class ReservationClientApplication {    public static void main(String[] args) {        SpringApplication.run(ReservationClientApplication.class, args);    }}

配置application.properties将端口设置为8800,配置eureka服务的地址(可选)。

server.port=8800eureka.instance.client.serviceUrl.defaultZone: http://localhost:8761/eureka/

代理使用

获取API服务信息

通过DiscoveryClient.getInstances(String)方法获得,其中参数为服务名(此例子中的reservation-service)。代码如下:

    @Autowired    private DiscoveryClient discoveryClient;    @RequestMapping("/service-instances/{applicationName}")    public List<ServiceInstance> serviceInstancesByApplicationName(            @PathVariable String applicationName) {        return this.discoveryClient.getInstances(applicationName);    }

此时通过访问代理地址,并加上服务名称参数,接口获得服务信息localhost:8800/service-instance/reservation-service:
这里写图片描述

直接转发API调用请求

仅需在代理地址上加上服务名和API名称即可:localhost:8800/reservation-service/reservations即可,下图是原接口与代理调用接口的结果对比:
这里写图片描述

作为中间件处理调用数据

代理具有拦截并处理原接口数据的功能,实现方式即将代理自身定义为WEB服务接受请求后,在调用原微服务获取数据,再对数据进行处理后返回给客户端。事例代码如下:

@RestController@RequestMapping("/reservations")class ReservationApiGatewayRestController{    @Autowired    private DiscoveryClient discoveryClient;//  @LoadBalanced    @Autowired    private RestTemplate restTemplate;    @RequestMapping("/names")    public Collection<String> getReservationNames(){        ParameterizedTypeReference<Resources<Reservation>> ptr =                 new ParameterizedTypeReference<Resources<Reservation>>() { };        String url = discoveryClient.getInstances("reservation-service").get(0).getUri()+"/reservations";        ResponseEntity<Resources<Reservation>> responseEntity =                 this.restTemplate.exchange(url,                 HttpMethod.GET, null, ptr);        return responseEntity                .getBody()                .getContent()                .stream()                .map(Reservation::getReservationName)                .collect(Collectors.toList());    }}

此例子将原接口返回的reservation实体处理后
,仅返回reservationName属性给客户端,达到保密隐藏其它属性的作用。调用结果如下:
这里写图片描述

0 0