Spring Cloud学习系列第一篇【服务治理】

  本篇随笔为学习Spring Cloud的第一篇,因此我从搭建微服务最基本的服务治理开始入手,之后每一篇都以此篇为基础拓展微服务其他内容。首先看下这篇随笔要完成的任务是什么?请看下图。这是一个最基础的微服务模型,我对图中的组件解析下。

  1. 采用了Eureka做注册中心,为了防止单点故障问题,我会启动2个Eureka并且互为向对方注册,这样即可搭建起高可用的一个注册中心。

  2. ServiceA为一个微服务应用并向注册中心注册自己,这里同样做了高可用。

  3. WebA为一个Web服务同样向注册中心注册自己,该服务是对外暴露的,WebA接受到了用户的http请求后,会向注册中心获取到ServiceA的地址,结合Spring Cloud Ribbon通过负载均衡的方式访问ServiceA。

  简单来说就是使用Eureka+Ribbon来实现服务治理。

  一、搭建高可用注册中心

  因为Eureka也是用java实现的,因此我们搭建起来很容易,这里要说明下我配置文件结构。从图中可以看出我要搭建2个Eureka Server,所以共性的配置需要放在application.properties文件,而application-peer1.properties和application-peer2.properties分别用来起Eureka Server1Eureka Server2的,Eureka Server1和EurekaServer2分别占用5001和5002端口,并且需要互相向对方注册!

  

  

  application.properties配置如下:

spring.application.name=eureka-server
server.port=5000

#调试环境需要关闭Eureka的自我保护
eureka.server.enable-self-preservation=false 

#搭建高可用注册中心需要向别的Eureka服务注册自己
eureka.client.register-with-eureka=true

#搭建高可用注册中心需要服务发现别的注册中心
eureka.client.fetch-registry=true

eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/

  application-peer1.properties配置如下:

server.port=5001

#向Eureka Server2注册自己
eureka.client.serviceUrl.defaultZone=http://localhost:5002/eureka/

  application-peer2.properties配置如下:

server.port=5002

#向Eureka Server1注册自己
eureka.client.serviceUrl.defaultZone=http://localhost:5001/eureka

  二、搭建ServiceA

  ServiceA这个微服务对内提供服务,主要提供服务写在UserController类里面,为了简单起见,我这里只提供了一个接口。同样的ServerA也是做成高可用的,分别用applicaion-peer1.properties和application-peer2.properties配置2个同的端口作为演示6001端口和6002端口。

  

 

  UserController类 

package com.pumpkin.controller;

import com.pumpkin.bean.User;
import com.pumpkin.service.UserService;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/user")
public class UserController {

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

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/{id}", method = RequestMethod.GET)
    public User get(@PathVariable String id) {
        LOGGER.info("request id=" +id);
        return userService.get(Integer.valueOf(id));
    }
}

  三、WebA

  WebA是对外提供服务,一般就是我们一些网站后台之类的,用于响应用户的http请求。这里我们要整合上Ribbon使其可以使用多种策略去访问其他微服务,默认是使用轮询的测试。要使用Ribbon首先要用于Spring Cloud Ribbon的依赖,并且使用Spring依赖注入RestTemplate对象,该对象会使用Ribbon的自动化配置,通过配置@LoadBlanced就可以开始客户端的负载均衡了。

  

  

  依赖引入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">
    <modelVersion>4.0.0</modelVersion>


    <groupId>com.pumpkin</groupId>
    <artifactId>pumpkin-web-a</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>WebA</name>
    <description>Spring Cloud Study</description>

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

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Brixton.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>

  依赖注入RestTemplate对象

package com.pumpkin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@EnableDiscoveryClient
@SpringBootApplication
public class Application {

    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
        return new RestTemplate();
    }

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

    }

}

  webAction

  该类主要提供对外服务。restTemplate.getForObject("http://SERVICE-A/user/1", String.class);这里直接使用ServerA的应用名去访问ServerA提供的服务(注意要大写) 

package com.pumpkin.web;


import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class webAction {
    private final Logger LOGGER = Logger.getLogger(getClass());

    @Autowired
    RestTemplate restTemplate;

    @RequestMapping(value = "/hello", method = RequestMethod.GET)
    public String hello() {
        LOGGER.info("hello.....");
        String response = restTemplate.getForObject("http://SERVICE-A/user/1", String.class);
        return response;
    }
}

 

  application.properties

默认情况下Eureka会通过心跳机制去检查注册上来的服务健康程度,是否可服务。如果希望Eureka通过访问/healthy端点去检查服务的健康情况,可以配置eureka.client.healthcheck.enabled=true,同时如果我们为应用设置了context-path要正确设置eureka.instance.statusPageUrlPath和eureka.instance.healthCheckUrlPath路径,不然Eureka就无法正确获取到我们应用的信息了。

spring.application.name=web-a
server.port=8080

#设置web访问前缀
server.context-path=/web

#ribbon.eureka.enabled=false
#SERVICE-A.ribbon.listOfServers=http://localhost:19210,http://localhost:11862
eureka.client.serviceUrl.defaultZone=http://localhost:5001/eureka/,http://localhost:5002/eureka/

eureka.client.healthcheck.enabled=true
management.context-path=/manager
eureka.instance.statusPageUrlPath=${server.context-path}/${management.context-path}/info
eureka.instance.healthCheckUrlPath=${server.context-path}/${management.context-path}/health

  四、测试

  最后我们启动一下写好的服务,Eureka和ServiceA可以通过java -jar xxx.jar --spirng.profiles.active=xxx的方式指定配置文件启动,比如ServiceA,可以用命令

java -jar pumpkin-service-a-1.0-SNAPSHOT.jar --spring.profiles.active=peer1和java -jar pumpkin-service-a-1.0-SNAPSHOT.jar --spring.profiles.active=peer2启动。

  

  访问http://127.0.0.1:5001或http://127.0.0.1:5002查看当前注册上了的服务,可以看到WebA和ServiceA都正确注册上来了

  访问:http://127.0.0.1:8080/web/hello,并且多次访问,可以看到后台2个ServiceA应用的日志是轮流着打印的。

  

  五、总结

  虽然到此Spring Cloud的服务治理就搭建完成,但其实里面还有很多细节可以深究的,比如Eureka如果判断服务是否可用,心跳机制的策略又是如何?Ribbon是如何工作的等等,但是一口气吃不成胖子,一篇随笔也不可能写得了方方面面,今天就从最简单的搭建工作做起,之后再慢慢完善吧。

  

  六、参考资料

  Spring Cloud微服务实战-翟永超。本系列的学习都是参考该书籍学习的,同时源码使用的Spring Boot和Spring Cloud的版本也与该书保持一致。

  七、源码

  待整理,上传码云

猜你喜欢

转载自www.cnblogs.com/yipaihushuo/p/9136716.html