:初探Spring Cloud Eureka+Hystrix+Ribbon+Feign微服务搭建

Posted S1ow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了:初探Spring Cloud Eureka+Hystrix+Ribbon+Feign微服务搭建相关的知识,希望对你有一定的参考价值。

凡是过去,皆为序章

通过自动配置和绑定到Spring环境和其他Spring编程模型的习惯方式来为Spring Boot应用程序提供Netflix OSS集成。通过几个简单的注释,您可以快速启用和配置应用程序中的常见模式,并通过经过测试的Netflix组件构建大型分布式系统。提供的模式包括服务发现(Eureka),断路器(Hystrix),智能路由(Zuul)和客户端负载平衡(Ribbon)。

通过上面几个组件可以轻松的搭建出一个分布式服务,如果研究过Dubbo的小伙伴们,应该可以轻松的理解分布式,下面就行动起来吧。


Now , show code.


说明:
1、一个配置服务,上一章中的cloud-demo-config,这里复用不讲解
2、1/N个Eureka服务,用于注册与发行服务,cloud-demo-eureka-server
3、1/N个服务提供者,用于向eureka注册服务,cloud-demo-service,简单的使用spring boot整合了Mybatis
4、一个web服务,用于从eureka发现cloud-demo-service注册的服务,一个简单的spring boot工程

第一步,创建cloud-demo-config配置服务工程,请见第一章。

这里所有的工程均采用了配置服务的方式进行远程配置的集中管理。

第二步,创建cloud-demo-eureka-server服务管理中心

1、使用阿里私服与spring Brixton配置方式的pom.xml:

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>

    <groupId>cloud-demo-eureka-server</groupId>
    <artifactId>cloud-demo-eureka-server</artifactId>
    <name>cloud-demo-eureka-server</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

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

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


    <dependencies>
        <!-- SpringCloud配置启动器 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <!-- SpringCloud实现的eureka服务注册于发布器 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka-server</artifactId>
        </dependency>
        <!-- 暴露相关管理监控 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
    </dependencies>

    <repositories>
        <repository>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            <id>public</id>
            <name>Public Repositories</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        </repository>
    </repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>Public Repositories</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        </pluginRepository>
    </pluginRepositories>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <defaultGoal>compile</defaultGoal>
    </build>
</project>

2、EurekaServer的启动类,两个注解一个main方法轻轻松松搞定,有没有爱上Spring,爱上Spring cloud:

package org.cloud.demo.eureka.server;

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

@SpringBootApplication
@EnableEurekaServer //开启Eureka服务,可以理解为注册中心
public class EurekaServer 

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

3、上一章工程中采用properties的配置,从本章节开始采用yml为配置文件,application.yml:

server: 
  port: 8761

#Spring Cloud Config配置信息
spring:
  application:
    name: cloudeureka
  cloud: 
    config: 
      uri: http://$config.server.ip:$config.server.port
      name: cloudeureka
      profile: $app.profile:test

#Eureka 配置信息
eureka:
  instance:
    hostname: $eureka.instance.hostname #暴露的hostname
  client:
    registerWithEureka: $eureka.client.registerWithEureka #是否注册到eureka
    fetchRegistry: $eureka.client.fetchRegistry #是否从eureka获取注册信息
    serviceUrl: 
      defaultZone: http://$eureka.instance.hostname:$server.port/eureka/ #serviceUrl指向与本地实例相同的主机
      #defaultZone: http://user:password@localhost:8761/eureka #带有安全验证的服务中心
    healthcheck: 
      enabled: true #默认是true,Eureka的监控检查,这个配置需要配置在application中,配置bootstrap中可能会导致一系列的问题

说明:
1、以上所有带有$的,均需要从Config Server去获取配置的信息
2、serviceUrl指向本地实例相同的主机
3、healthcheck:默认是true,Eureka的监控检查,这个配置需要配置在application中,配置bootstrap中可能会导致一系列的问题

以上,一个EurekaServer就搭建完成了。

第三步、创建cloud-demo-service服务的提供者,由于集成了Mybatis,代码可能会比较长,点击这里查看好了

说明:
将第三步中的工程使用package进行打包,使用以下命令在cmd中运行:
1、java -jar cloud-demo-service-1.3.5.RELEASE.jar –server.port=8081
2、java -jar cloud-demo-service-1.3.5.RELEASE.jar –server.port=8082
3、。。。。

第四步、搭建服务的消费者cloud-demo-web

1、相差无几的pom文件,引入需要的负载ribbon、http请求feign,熔断器hystrix。pom.xml:

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>cloud-demo-web</groupId>
  <artifactId>cloud-demo-web</artifactId>
  <name>cloud-demo-web</name>
  <url>http://maven.apache.org</url>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.3.5.RELEASE</version>
    </parent>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Brixton.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <repositories>
        <repository>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
            <id>public</id>
            <name>Public Repositories</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>public</id>
            <name>Public Repositories</name>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        </pluginRepository>
    </pluginRepositories>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- spring-cloud-starter-feign 里面已经包含了 spring-cloud-starter-ribbon(Feign 中也使用了 Ribbon)-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <!-- 使用hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jolokia</groupId>
            <artifactId>jolokia-core</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <defaultGoal>compile</defaultGoal>
    </build>

</project>

2、消费方的启动类

package org.cloud.demo.web;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.web.client.RestTemplate;

import feign.Feign;
import feign.Logger;
import feign.Request;

@SpringBootApplication
@EnableEurekaClient
//开启断路器
@EnableCircuitBreaker  
//开启Feign功能
@EnableFeignClients
public class WebApplication 

    private static final int FIVE_SECONDS = 5000;

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

    @LoadBalanced //开启软负载均衡
    @Bean
    RestTemplate restTemplate()
        return new RestTemplate();
    

    @Bean
    @Scope("prototype")
    public Feign.Builder feignBuilder()
        return Feign.builder();
    

    @Bean
    public Logger.Level feignLogger()
        return Logger.Level.FULL;
    

    @Bean
    public Request.Options options()
        return new Request.Options(FIVE_SECONDS, FIVE_SECONDS);
    

3、配置文件,application.yml

server:
  port: 8090

spring: 
  application: 
    name: cloudweb
  cloud:
    config:
      uri: http://$config.server.ip:$config.server.port
      name: cloudweb
      profile: $app.profile:test

#service discovery url
eureka: 
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

#ribbon服务配置
cloudservice:
  ribbon:
    ConnectTimeout: 5000
    ReadTimeout: 10000

说明:ribbon服务配置如果在WebApplication中开启了@LoadBalanced,一定不要配置错了,否则会发生访问不稳定的情况。

4、用于获取远程服务Service ,这里分别采用了RestTemplate与Feign两种方式进行实现:

  • RestTemplate 方式的UserService
package org.cloud.demo.web.service;

import java.util.ArrayList;
import java.util.List;

import org.cloud.demo.web.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

//Ribbon实现方式
@Service
public class UserService 

    @Autowired
    RestTemplate restTemplate;

    @Value("$service.name:cloudservice")
    String SERVICE_NAME;

    @SuppressWarnings("unchecked")
    @HystrixCommand(fallbackMethod = "fallbackSearchAll")
    public List<User> readUserInfo() 
         return restTemplate.getForObject("http://"+ SERVICE_NAME +"/user/getAllUsers", List.class);
    

    @SuppressWarnings("unused")
    private List<User> fallbackSearchAll() 
         System.out.println("HystrixCommand fallbackMethod handle!");
         List<User> ls = new ArrayList<User>();
         User user = new User();
         user.setName("ivan");
         ls.add(user);
         return ls;
    

说明:
1、带有$均从远程配置服务获取配置信息
2、使用了熔断器Hystrix,配置有很多种,这里仅仅为了演示使用了fallbackMethod

  • Feign实现的UserServiceByFeign,是一个接口,它的好处在于调用服务时,就像调用本地服务一样,傻傻分不清呀
package org.cloud.demo.web.service;

import java.util.List;

import org.cloud.demo.web.model.User;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

//绑定該接口到服务名称,通过config管理服务,并通知Feign组件对该接口进行代理(不需要编写接口实现)
@FeignClient(value="cloudservice",fallback=UserServiceByFeignImple.class)
public interface UserServiceByFeign 

    @RequestMapping(value="/user/getAllUsers",method=RequestMethod.GET)
    List<User> getAllUsers();

说明:RequestMapping中的value对应服务提供者暴露的rest路径

fallback的实现,因为fallback需要返回值,参数,方法名均相同,所以直接实现UserServiceByFeign即可:

package org.cloud.demo.web.service;

import java.util.ArrayList;
import java.util.List;

import org.cloud.demo.web.model.User;
import org.springframework.stereotype.Component;

@Component
public class UserServiceByFeignImple implements UserServiceByFeign

    @Override
    public List<User> getAllUsers() 
        return new ArrayList<User>();
    


5、对外提供rest接口,UserController:

package org.cloud.demo.web.controller;

import java.util.List;

import javax.annotation.Resource;

import org.cloud.demo.web.model.User;
import org.cloud.demo.web.service.UserService;
import org.cloud.demo.web.service.UserServiceByFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController 

    @Autowired
    UserService userService;

    @Resource
    UserServiceByFeign userSeriveFeign;

    @RequestMapping(value="/getAllUsers")
    @ResponseBody
    public ResponseEntity<List<User>> getAllUsers()
        return new ResponseEntity<List<User>>(userService.readUserInfo(), HttpStatus.OK);
    

    @RequestMapping(value="/getUsersFeign")
    @ResponseBody
    public ResponseEntity<List<User>> getUsersFeign()
        return new ResponseEntity<List<User>>(userSeriveFeign.getAllUsers(), HttpStatus.OK);
    

以上,服务消费者demo版也就ok了。

Get it.

以上是关于:初探Spring Cloud Eureka+Hystrix+Ribbon+Feign微服务搭建的主要内容,如果未能解决你的问题,请参考以下文章

:初探Spring Cloud Config配置集中管理

:初探Spring Cloud Config配置集中管理

Spring Cloud构建微服务架构:服务容错保护(Hystrix服务降级)

Spring Cloud集成相关优质项目推荐

spring cloud 之 Eureka

spring cloud 之eureka配置