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

来源:互联网 发布:google 云计算 入华 编辑:程序博客网 时间:2024/04/26 12:39

凡是过去,皆为序章

通过自动配置和绑定到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功能@EnableFeignClientspublic 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: 8090spring:   application:     name: cloudweb  cloud:    config:      uri: http://${config.server.ip}:${config.server.port}      name: cloudweb      profile: ${app.profile:test}#service discovery urleureka:   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实现方式@Servicepublic 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;@Componentpublic 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;@RestControllerpublic 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了。

  • 启动config服务
  • 启动eureka服务,可访问http://127.0.0.1:8761进入管理页
  • 使用java -jar cloud-demo-service-1.3.5.RELEASE.jar –server.port=8081 启动service服务
  • 使用java -jar cloud-demo-service-1.3.5.RELEASE.jar –server.port=8082 启动service服务
  • 启动web服务
  • 访问http://127.0.0.1:8090/getAllUsers
  • 访问http://127.0.0.1:8090/getUsersFeign

Get it.

阅读全文
0 0
原创粉丝点击