Spring Cloud入门与实践(一)-Eureka

版权声明:本博客所有的原创文章,转载请注明出处,作者皆保留版权。 https://blog.csdn.net/anLA_/article/details/80632865

微服务,很火的一个概念,无数的架构师和开发者在实际项目中实践该设计理念并为此付出了诸多努力,同时也涌现出针对不同应用场景出现的各种问题的各种解决方案和开源框架,

  • 服务治理例如Dubbo,Netflix的Eureka。
  • 分布式配置管理Spring Cloud的Config等。
  • 批量任务例如Spring Cloud的Task,LinkedIn的Azkaban
  • 服务跟踪入京东的Hydra,Spring Cloud的SleuthDENG1

Spring Cloud的出现,可以说是对微服务框架的巨大支持和强有力的技术后盾,它不像前面框架所说的,只是解决微服务中的某一个问题,而是一个解决微服务架构实施的综合性解决框架,它整合了诸多广泛实践和证明过的框架作为实施的基础部件,又在该体系基础上创建了一些非常优秀的边缘组件。

Spring Cloud是一个基于Spring Boot实现的微服务架构开发工具,他为服务架构中设计的配置管理,服务治理,断路器,智能路由,微代理,控制总线,全局锁,决策竞选,分布式会话等提供了集群状态等操作提供了一种简单的开发方式。

Whta is Eureka

本篇文章主要介绍Spring Cloud Eureka,它基于Netflix Eureka做了二次封装,主要完成微服务框架中服务治理功能。
Eureka是以服务器/客户端模式,客户端(其他微服务系统)通过向Eureka注册中心进行注册。

例子

就基于Spring Boot的例子来说,Spring Cloud Eureka的Hello World是十分简单的

Server端

  1. 首先配置pom文件:
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.13.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

上面几个节点,开始总是想着Spring Boot用2.0.0.release版本,并且Spring-Cloud使用Edgware.SR3 版本,事实上就是各种报错,因为高版本低版本会有类冲突,会报错NoSuchMethodError: org.springframework.boot.builder.SpringApplicationBuilder.<init>
具体可看:https://stackoverflow.com/questions/44166221/spring-boot-2-0-0-m1-nosuchmethoderror-org-springframework-boot-builder-springa
不过对于具体Spring Boot和Spring Cloud版本之间的具体版本关系推荐去Spring 官网看:
https://projects.spring.io/spring-cloud/#quick-start

对于spring-boot-starter-test ,版本是通过parent标签来确定的。

  1. 编写一个包含main方法的启动类:
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }

}

通过@EnableEurekaServer注解启动一个服务注册中心,提供其他应用进行对话。
在默认配置下面,该服务注册中心也会讲自己作为客户端来尝试注册自己,所以如果是单服务注册中心,需要禁止自己注册自己,
如果是多注册中心,实现高可用,则需要相互注册。

  1. application.yml配置
server:
  port: 8761                        #端口

eureka:
  instance:
    hostname: localhost             #实例名称
  client:
    registerWithEureka: false       #该应用为注册中心,这个代表不能自己注册自己
    fetchRegistry: false            #注册中心职责维护服务示例,不需要去检索服务,设为false
  server:
    waitTimeInMsWhenSyncEmpty: 0    #立即检索

成功进入之后,则可以看到如下页面:
这里写图片描述

Client端

刚刚实现了一个Eureka服务注册中心,现在来实现一个Spring Boot应用加入到Eureka的服务治理体系中去
1. pom文件:

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.13.RELEASE</version>
    </parent>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Edgware.SR3</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

具体pom依赖和eureka服务端类似,参考上面解释!

  1. 实现一个Eureka的客户端:
@EnableDiscoveryClient
@SpringBootApplication
public class HelloServiceApplication {
    public static void main(String[] args){
        SpringApplication.run(HelloServiceApplication.class,args);
    }
}
  1. 实现一个业务Controller:
@RestController
public class HelloController {

    private final Logger logger = Logger.getLogger(getClass());

    @Autowired
    private DiscoveryClient client;

    @RequestMapping(value = "/hello",method = RequestMethod.GET)
    public String index(){
        ServiceInstance config = client.getInstances("localhost").get(0);
        logger.info("/hello-service:"+config.getHost() +"--------service_id:"+config.getServiceId());
        return "hello-service";
    }
}

很简单的一个RestController,通过@Autowired注入。在

ServiceInstance config = client.getInstances("localhost").get(0);

因为getLocalServiceInstance已经被废弃了,所以需要用getInstances来获取
getInstances中,输入eureka Serverinstance name,从而获取所有实例(非公有)。

  1. application.yml配置如下:
spring:
  application:
    name: hello-service                                    #为服务命名

eureka:
  client:
    serviceUrl:
      #defaultZone: http://localhost:8761/eureka/           #指定开始的eureka server的注册中心
      defaultZone: http://${eureka.host:localhost}:${eureka.port:8761}/eureka/     #推荐这种方法

当Eureka Client启动时,在Eureka Server会有一段日志输出,说明有新服务注册进来:

2018-06-09 17:11:07.946  INFO 11568 --- [nio-8761-exec-8] c.n.e.registry.AbstractInstanceRegistry  : 
Registered instance HELLO-SERVICE/192.168.1.107:hello-service with status UP (replication=false)

另一方面,当重启Eureka Client启动时,相应也会有一段输出,当然如果是直接重启(没有任何修改),则Eureka Client注册状态返回
为204。204代表服务器返回的信息为未修改,即没有任何改变。

2018-06-09 17:11:07.948  INFO 14356 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : 
DiscoveryClient_HELLO-SERVICE/192.168.1.107:hello-service - registration status: 204

此时看看Eureka Server的界面:
这里写图片描述

注意界面上有一串红色文字:

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. 
RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE.

这个警告是因为触发了Eureka Server的自我保护机制,因为服务注册到Eureka Server之后,会维护一个心跳连接,告诉Eureka Server自己还活着。Eureka Server在运行期间,会统计心跳失败的比例在15分钟内,是否低于85%。低于就会报警。
因为一旦出现这种问题,那么客户端很容易拿到实际已经不存在的服务示例,会出现调用失败的情况,所以客户端必须有容错机制,比如可以使用请求,断路器等机制。

另外可以在application.yml中增加eureka.server.enable-self-preservation=false来关闭保护机制。

一个简单的Eureka Server和Eureka Client已完成。
下面将使用采用一体化将其发布到docker中。

Docker 中运行

利用docker-maven-plugin插件,来实现对Spring Boot项目的打包

eureka-server

首先项目目录为:
这里写图片描述

在目录eureka-server的pom文件增加插件:

            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <configuration>
                    <imageName>${project.name}:${project.version}</imageName>
                    <dockerDirectory>${project.basedir}/src/main/docker</dockerDirectory>
                    <skipDockerBuild>false</skipDockerBuild>
                    <resources>
                        <resource>
                            <directory>${project.build.directory}</directory>
                            <include>${project.build.finalName}.jar</include>
                        </resource>
                    </resources>
                </configuration>
            </plugin>

由上面可知,<dockerDirectory> 配置了Dockerfile配置,即在Java同级目录增加一个docker文件夹,并在里面编写Dockerfile

FROM java:8
VOLUME /tmp/docker
RUN mkdir /app
COPY eureka-server-1.0-SNAPSHOT.jar /app/app.jar
COPY runboot.sh /app/
RUN bash -c 'touch /app/app.jar'
WORKDIR /app
RUN chmod a+x runboot.sh
EXPOSE 8761
CMD /app/runboot.sh

另外runboot.sh:

java -Djava.security.egd=file:/dev/./urandom -jar /app/app.jar

关于-Djava.security.egd=file:/dev/./urandom 主要目的就是来生成一个随机数,关于随机数生成时,采用的“熵源”(entropy source)的策略。
参看:http://ifeve.com/jvm-random-and-entropy-source/

hello-service

在hello-service中的配置与eureka-server类似,这里就不赘述

docker-compose

docker-compose是docker三架马车之一,采用python编写,可以理解为把一些Dockerfile里面命令,整合到一起。比如我要启动一个Eureka服务器,然后启动一个客户端,此时需要用docker启动Eureka-server,然后在用docker启动hello-service,此时要执行两遍命令。
采用docker-compose,我们只需要执行docker-compose up执行就可以了,例如本项目中:

version: "1"
services:
  eureka-server:
    image: "eureka-server:1.0-SNAPSHOT"
    hostname: eureka-server
    container_name: eureka-server
    ports:
     - "8761:8761"

  hello-service:
    image: "hello-service:1.0-SNAPSHOT"
    hostname: hello-service
    container_name: hello-service
    links:
      - eureka-server                  #链接到另一个容器
    environment:
       EUREKA_HOST: eureka-server
       EUREKA_PORT: 8761

具体代码文件上传到了csdn,需要的同学可自行下载,然后按以下步骤执行:
https://download.csdn.net/download/anla_/10469436
1. mvn clean package docker:build
2. docker-compose up

猜你喜欢

转载自blog.csdn.net/anLA_/article/details/80632865