Spring Cloud Netflix构建微服务入门实践

标签: Spring 开源技术 Eureka SpringCloud | 发表时间:2017-03-03 09:01 | 作者:Yanjun
分享到:
出处:http://shiyanjun.cn

在使用Spring Cloud Netflix构建微服务之前,我们先了解一下Spring Cloud集成的Netflix OSS的基础组件Eureka,对于Netflix的其他微服务组件,像Hystrix、Zuul、Ribbon等等本文暂不涉及,感兴趣可以参考官网文档。这里,我们用最基础的Eureka来构建一个最基础的微服务应用,来演示如何构建微服务,了解微服务的基本特点。

Eureka

Eureka是Netflix开源的一个微服务注册组件,提供服务发现特性,它是一个基于REST的服务,主要具有如下功能:

  • 支持服务注册和发现
  • 具有Load Balance和Failover的功能
  • 在进行服务调用过程中,无需知道目标服务的主机(IP)和端口,只要知道服务名就可以实现调用

通过Netfix在Github上的文档,我们看一下Eureka的基本架构,如下图所示:
eureka_architecture
Eureka主要包含如下两个核心组件:

  • Eureka Server

Eureka Server是服务注册的服务端组件,负责管理Eureka Client注册的服务,提供服务发现的功能。它支持集群模式部署,集群部署模式中,多个Eureka Server之间会同步服务注册数据,能够保证某一个Eureka Server因为故障挂掉,仍能对外提供注册服务的能力。因为最初在Netflix,Eureka主要用在AWS Cloud上,用作定位服务、Load Balance和Failover,在AWS Cloud上,Eureka支持在多个Region中部署Eureka Server而构建一个注册中心集群,从而实现了服务注册中心的高可用性。

  • Eureka Client

Eureka Client是Eureka Server客户端组件库,可以基于它向Eureka Server注册服务,供服务调用方调用;也可以是一个服务调用方,通过检索服务并调用已经注册的服务。如上图所示,Application Service和Application Client都是基于Eureka Client开发的使用Eureka Server的服务。另外,Eureka Client提供了内置的Load Balancer,实现了基本的Round-robin模式的负载均衡。

Spring Cloud Netflix

Spring Cloud Netflix提供了对Netflix OSS的集成,同时还使用了Spring Boot,能够极大地简化微服务程序的开发。使用Spring Cloud提供的基本注解,就能非常方便的使用Netfix OSS基本组件。
要想使用Spring Cloud Eureka,只需要在Maven POM文件中加入如下依赖管理配置即可:

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-netflix</artifactId>
                <version>1.0.7.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

关于如何使用注解,我们会在下面的实践中,详细说明。

构建微服务实践

我们构建一个简单的微服务应用,能够实现服务注册,服务调用的基本功能。计划实现的微服务应用,交互流程如下图所示:
eureka-service-interaction
上图中,我们假设Eureka Client并没有缓存Eureka Server中注册的服务,而是每次都需要通过Eureka Server来查找并映射目标服务。上图所示的微服务应用,具有如下服务组件:

  • 两个Eureka Server实例组成的服务发现集群

通过Spring Cloud实现,只需要使用注解配置即可,代码如下所示:

package org.shirdrn.springcloud.eureka.server;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@EnableEurekaServer
@SpringBootApplication
public class MyEurekaServer {

    public static void main(String[] args) {
        new SpringApplicationBuilder(MyEurekaServer.class).web(true).run(args);
    }
}

部署两个Eureka Server的代码是相同的,其中,对应的配置文件application.yml内容不同,示例如下所示:

server:
  port: 3300
spring:
  application:
    name: my-eureka-server
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:3300/eureka/,http://localhost:3301/eureka/
  instance:
    metadataMap:
      instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}

另一个只需要改一下server.port为3301即可。

  • 具有两个实例的Greeting Service服务

该示例服务,只是提供一个接口,能够给调用方返回调用结果,实现代码,如下所示:

package org.shirdrn.springcloud.eureka.applicationservice.greeting;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@EnableEurekaClient
@RestController
@EnableAutoConfiguration
public class GreeingService {

    @RequestMapping(method = RequestMethod.GET, value = "/greeting/{name}")
    public String greet(@PathVariable("name") String name) {
        return "::01:: Hello, " + name + "!";
    }

    public static void main(String[] args) {
        new SpringApplicationBuilder(GreeingService.class).web(true).run(args);
    }
}

为了能够观察,Greeting Service的两个实例,能够在调用的时候实现Round-robin风格的负载均衡,特别在返回的结果中增加了标识来区分。
对应的配置文件application.properties内容,除了对应的端口和服务实例名称不同,其它都相同,示例如下所示:

server.port=9901
spring.application.name = greeting.service
eureka.instance.metadataMap.instanceId = ${spring.application.name}:instance-9901
eureka.client.serviceUrl.defaultZone = http://localhost:3300/eureka/,http://localhost:3301/eureka/

这样就可以在启动时注册到Eureka Server中。

  • 一个名称为Application Caller的服务,需要调用Greeting Service服务

该服务和上面的服务类似,只是在其内部实现了对远程服务的调用,我们的实现代码如下所示:

package org.shirdrn.springcloud.eureka.applicationclient.caller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class Application {

    public static void main(String[] args) {
        new SpringApplicationBuilder(Application.class)
                .web(false)
                .run(args);
    }
}

@Component
class RestTemplateExample implements CommandLineRunner {

    @Autowired
    private RestTemplate restTemplate;
    private static final String GREETING_SERVICE_URI = "http://greeting.service/greeting/{name}";  // 通过服务名称来调用,而不需要知道目标服务的IP和端口

    @Override
    public void run(String... strings) throws Exception {
        while(true) {
            String greetingSentence = this.restTemplate.getForObject(
                    GREETING_SERVICE_URI,
                    String.class,
                    "Dean Shi"); // 透明调用远程服务
            System.out.println("Response result: " + greetingSentence);

            Thread.sleep(5000);
        }
    }
}

对应的配置文件application.properties内容,如下所示:

server.port=9999
spring.application.name = application.client.caller
eureka.instance.metadataMap.instanceId = ${spring.application.name}:instance-9999
eureka.client.serviceUrl.defaultZone = http://localhost:3300/eureka/,http://localhost:3301/eureka/

启动并验证微服务应用

上面已经实现了该示例微服务应用的全部组件,先可以启动各个服务组件了。启动顺序如下所示:

  1. 启动两个Eureka Server
  2. 启动两个Greeting Service
  3. 启动服务消费应用Application Call

可以通过Web页面查看Eureka Server控制台,如下图所示:
eureka-web-console
多次启动Application Call应用,就可以通过查看Greeting Service服务的日志,可以看到服务被调用,而且实现了基础的Round-robin负载均衡,日志如下所示:

Response result: ::02:: Hello, Dean Shi!
Response result: ::01:: Hello, Dean Shi!
Response result: ::02:: Hello, Dean Shi!
Response result: ::01:: Hello, Dean Shi!
Response result: ::02:: Hello, Dean Shi!
Response result: ::01:: Hello, Dean Shi!

我们实现示例微服务应用,验证后符合我们的期望。
上面微服务应用的实现代码及其配置,可以查看我的Github: https://github.com/shirdrn/springcloud-eureka-demo.git

参考链接

相关 [spring cloud netflix] 推荐:

Spring Cloud Netflix构建微服务入门实践

- - 简单之美
在使用Spring Cloud Netflix构建微服务之前,我们先了解一下Spring Cloud集成的Netflix OSS的基础组件Eureka,对于Netflix的其他微服务组件,像Hystrix、Zuul、Ribbon等等本文暂不涉及,感兴趣可以参考官网文档. 这里,我们用最基础的Eureka来构建一个最基础的微服务应用,来演示如何构建微服务,了解微服务的基本特点.

大话 Spring Cloud

- - IT瘾-dev
研究了一段时间spring boot了准备向spirng cloud进发,公司架构和项目也全面拥抱了Spring Cloud. 在使用了一段时间后发现Spring Cloud从技术架构上降低了对大型系统构建的要求,使我们以非常低的成本(技术或者硬件)搭建一套高效、分布式、容错的平台,但Spring Cloud也不是没有缺点,小型独立的项目不适合使用.

微服务框架Spring Cloud介绍 Part2: Spring Cloud与微服务

- - skaka的博客
之前介绍过 微服务的概念与Finagle框架, 这个系列介绍Spring Cloud.. Spring Cloud还是一个相对较新的框架, 今年(2016)才推出1.0的release版本. 虽然Spring Cloud时间最短, 但是相比我之前用过的Dubbo和Finagle, Spring Cloud提供的功能最齐全..

为Spring Cloud Ribbon配置请求重试(Camden.SR2+)

- - 程序猿DD
下面的例子,实现了对服务名为 hello-service的 /hello接口的调用. 由于 RestTemplate被 @LoadBalanced修饰,所以它具备客户端负载均衡的能力,当请求真正发起的时候,url中的服务名会根据负载均衡策略从服务清单中挑选出一个实例来进行访问. 大多数情况下,上面的实现没有任何问题,但是总有一些意外发生,比如:有一个实例发生了故障而该情况还没有被服务治理机制及时的发现和摘除,这时候客户端访问该节点的时候自然会失败.

使用Spring Cloud和Docker构建微服务架构

- - Oopsguy
原文: https://dzone.com/articles/microservice-architecture-with-spring-cloud-and-do. 作者:Alexander Lukyanchikov. 如何使用Spring Boot、Spring Cloud、Docker和Netflix的一些开源工具来构建一个微服务架构.

微服务应用-基于Spring Cloud和Docker构建电影推荐微服务

- - CSDN博客推荐文章
使用Spring Cloud和Docker构建电影推荐微服务. 如果你对云应用很了解,可以直接移步下载运行项目(https://github.com/kbastani/spring-cloud-microservice-example),或跳转到部署步骤,. 本博客系列将向你介绍一些使用Spring Cloud和Docker构建微服务平台的基本概念.

微服务架构的基础框架选择:Spring Cloud还是Dubbo?

- - 程序猿DD
最近一段时间不论互联网还是传统行业,凡是涉及信息技术范畴的圈子几乎都在讨论 微服务架构. 近期也看到各大技术社区开始组织一些沙龙和论坛来分享Spring Cloud的相关实施经验,这对于最近正在整理Spring Cloud相关套件内容与实例应用的我而言,还是有不少激励的. 目前,Spring Cloud在国内的知名度并不高,在前阵子的求职过程中,与一些互联网公司的架构师、技术VP或者CTO在交流时,有些甚至还不知道该项目的存在.

Spring Cloud实践:降级、限流、滚动、灰度、AB、金丝雀的实现思路

- - 程序猿DD | 博客
之前在我博客的 问答平台和 Spring4All社区均有关于Spring Cloud的发布策略实现问题. 虽然大家都给力很多不错的思路和建议,但是都没有 Charles He的这篇文章详细. 因此经得作者同意,在这里转载了该篇内容,为了更好的阅读体验,稍作一些格式调整,分享给更多Spring Cloud爱好者.

spring cloud 实践-降级、限流、滚动、灰度、AB、金丝雀等等等等 - 简书

- -
spring cloud 实践. 源码地址:https://github.com/charlesvhe/spring-cloud-practice. 端口:8888,方便起见直接读取配置文件,生产环境可以读取git. application-dev.properties为全局配置. 先启动配置中心,所有服务的配置(包括注册中心的地址)均从配置中心读取.

聊聊 API Gateway 和 Netflix Zuul

- - ScienJus's Blog
最近参与了公司 API Gateway 的搭建工作,技术选型是 Netflix Zuul,主要聊一聊其中的一些心得和体会. 本文主要是介绍使用 Zuul 且在不强制使用其他 Neflix OSS 组件时,如何搭建生产环境的 Gateway,以及能使用 Gateway 做哪些事. 不打算介绍任何关于如何快速搭建 Zuul,或是一些轻易集成 Eureka 之类的的方法,这些在官方文档上已经介绍的很明确了.