《Spring Colud》 Eureka 服务治理详解与高可用分布式搭建

这篇笔记主要讲述利用spring cloud eureka来进行服务管理、高可用和负载均衡。
一、什么是Eureka
     Eureka是Netflix开源的一个RESTful服务,主要用于服务的注册发现。Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。Netflix在其生产环境中使用的是另外的客户端,它提供基于流量、资源利用率以及出错状态的加权负载均衡。
     在我看来,Eureka的吸引力来源于以下几点:
  • 开源:大家可以对实现一探究竟,甚至修改源码。
  • 可靠:经过Netflix多年的生产环境考验,使用应该比较靠谱省心
  • 功能齐全:不但提供了完整的注册发现服务,还有Ribbon等可以配合使用的服务。
  • 基于Java:对于Java程序员来说,使用起来,心里比较有底。
  • spring cloud:可以使用Spring Cloud, 与Eureka进行了很好的集成,使用起来非常方便。

二、搭建服务注册中心
1、创建maven项目eureka-server,修改pom.xml文件如下:


    4.0.0
    eureka-server
    jar
    eureka-server Maven Webapp
    http://maven.apache.org

    
        learn.eureka.server.ApplicationEurekaServer
        UTF-8
        UTF-8
        1.8
        1.8
        1.8
        1.8
    

    
        org.springframework.boot
        spring-boot-starter-parent
        1.5.10.RELEASE
    

    

        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.cloud
            spring-cloud-starter-eureka-server
            1.3.1.RELEASE
        
        
        
            junit
            junit
            4.12
            test
        
    

    
        
            
                org.springframework.cloud
                spring-cloud-config
                1.3.1.RELEASE
                pom
                import
            
            
                org.springframework.cloud
                spring-cloud-netflix
                1.3.1.RELEASE
                pom
                import
            
        
    

    
        eureka-server
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
        
    

2、创建启动类,并注解@EnableEurekaServer 明该服务为服注册服务端微服务。

@SpringBootApplication
@EnableEurekaServer
public class ApplicationEurekaServer {
    public static void main(String[] args) {
        SpringApplication.run(ApplicationEurekaServer.class , args);
    }
}
配置application.yml文件
《Spring Colud》 Eureka 服务治理详解与高可用分布式搭建_第1张图片
3、启动之后在浏览器访问: http://localhost:1112 ( 我指定的端口是1112),得到如下界面表示启动成功。
peer1是该eureka服务端的项目名称,该名称在application.yml中设置:
spring:
  application:
    name: peer2
 eureka 会默认把自己也当作服务注册,这在以后做高可用的时候会用到。
  • eureka.client.register-with-eureka: 由于该应用为注册中心,所以设置 false, 代表不向注册中心注册自己。
  • eureka.client.fe七ch-registry: 由于注册中心的职责就是维护服务实例,它并不需要去检索服务, 所以也设置为 false 
三、注册服务提供者到服务注册中心
1、创建service-user项目,仿照(二)中(1)pom.xml构建maven项目。同时替换eureka服务端为客户端依赖。如下:
修改如下内容


    org.springframework.cloud
    spring-cloud-starter-eureka-server
    1.3.1.RELEASE

为:

    org.springframework.cloud
    spring-cloud-starter-eureka
    1.3.1.RELEASE

修改后完整pom文件如下:



    4.0.0
    service-user
    jar
    service-user Maven Webapp
    http://maven.apache.org

    
        org.springframework.boot
        spring-boot-starter-parent
        1.5.10.RELEASE
    

    
        com.learning.ServiceUserApplication
        UTF-8
        UTF-8
        1.8
        1.8
        1.8
        1.8
    

    
        
            
                org.springframework.cloud
                spring-cloud-config
                1.3.1.RELEASE
                pom
                import
            
            
                org.springframework.cloud
                spring-cloud-netflix
                1.3.1.RELEASE
                pom
                import
            
        
    

    
        
        
            com.alibaba
            fastjson
            1.2.24
        

        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-starter-test
            1.5.9.RELEASE
            test
        

        
        
             org.springframework.boot
            spring-boot-starter-actuator
        

        
            org.springframework.cloud
            spring-cloud-starter-eureka
            1.3.1.RELEASE
        

        
            junit
            junit
            4.12
            test
        

    

    
        service-user
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
            
            
                org.apache.maven.plugins
                maven-surefire-plugin
                
                    true
                
            
        
    

2、创建启动类,并注解@EnableEurekaClient 明该服务为服注册服务端微服务。

/**
 * @author [email protected]
 * @date 2018/2/22 18:22
 */
@EnableEurekaClient
@SpringBootApplication
public class ServiceUserApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceUserApplication.class , args);
    }
}

配置application.yml文件

server:
  port: 8001
spring:
  application:
    name: service-user
eureka:
  client:
    service-url:
#      defaultZone: http://peer2:1112/eureka/, http://peer1:1111/eureka/
      defaultZone: http://localhost:1112/eureka/
    healthcheck:
      enabled: true #使用health端点来代替心跳表明服务是否可用,反应到eureka server ui上服务的UP还是DOWN
  instance:
    lease-expiration-duration-in-seconds: 30 #租期更新时间间隔(默认30秒)
    lease-renewal-interval-in-seconds: 10 #租期更新时间间隔(默认30秒)
info:
  app:
    name: "@project.name@" #从pom.xml中获取
    description: "@project.description@"
    version: "@project.version@"
    spring-boot-version: "@project.parent.version@"

3、启动之后在浏览器访问:http://localhost:1111我指定的端口是1111),得到如下界面表示启动成功。

《Spring Colud》 Eureka 服务治理详解与高可用分布式搭建_第2张图片

四、高可用注册中心
    在微服务这样的分布式架构中,我们需要考虑单节点的故障。eureka server在设计之出就对该问题进行 了解决。在eureka中,服务的提供者同时也是服务的消费者,在第一个eureka server服务端中我们通过。
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false 
来设置服务注册中心不将自己注册到服务中心,而eureka的高可用就是将自己当作服务提供者注册到服务注册中心。
    我们以(二)中的服务注册中心为基础,来搭建高可用服务注册中心。
1、我们准备创建peer1、peer2两个服务注册中心来提供服务,即两个节点。首先,我们在hosts文件中队peer1、peer2进行一下ip映射。 /etc/hosts文件中添加对peerl  peer2的转换, 让上面配置的host形式的 serviceUrl能在本地正确访间到; Windows系统路径为C:\Windows\System32\ drivers\etc\hosts  
2、创建application-peer 1.yml文件,作为 peer1的服务注册中心。详细yml内容如下:
spring:
  application:
    name: peer1
  profiles:
    active: peer1 # 多平台打包部署启动,用来启动时指定使用的配置文件
server:
  port: 1111
eureka:
  server:
    enable-self-preservation: false #关闭自我保护,服务关闭后从列表中踢除,默认true,开启自我保护
    eviction-interval-timer-in-ms: 60000 # 清理间隔(单位毫秒,默认是60*1000)
  client:
    enabled: true
    register-with-eureka: true # 允许注册自己到服务注册中心
    fetch-registry: true #默认是true,允许服务定时任务定时刷新服务列表
    registry-fetch-interval-seconds: 60 # 定时任务执行时间,每隔60s刷新服务列表
    service-url:
      defaultZone: http://peer2:1112/eureka/ # 需要注册到的服务中心的地址
  instance:
    hostname: peer1 # 给主机命名

3、创建application-peer2.yml文件,作为peer2的服务注册中心。详细yml内容如下:

spring:
  application:
    name: peer2
  profiles:
      active: peer2 # 多平台打包部署启动,用来启动时指定使用的配置文件
server:
  port: 1112
eureka:
  server:
    enable-self-preservation: false # 关闭自我保护,服务关闭后从列表中踢除,默认是true,开启自我保护
    eviction-interval-timer-in-ms: 60000 # 清理间隔(单位毫秒,默认是60*1000)
  client:
    enabled: true
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://peer1:1111/eureka/
  instance:
    hostname: peer2
4、启动
    使用maven打包之后,我们可以通过如下命令分别启动peer1和peer2.
java -jar eureka-server.jar --spring.profiles.active=peer1
java -jar eureka-server.jar --spring.profiles.active=peer2

首先我们访问http://localhost:1111

《Spring Colud》 Eureka 服务治理详解与高可用分布式搭建_第3张图片

我们发现,服务注册peer1、peer2都注册到peer1中了,我们在访问Http://localhost:1112,

《Spring Colud》 Eureka 服务治理详解与高可用分布式搭建_第4张图片

服务注册peer1、peer2同样也注册到peer2中了。
5、现在我们使用前边说的service-user服务,同时向两个服务注册中心peer1、peer2注册。然后启动。yml配置如下:
server:
  port: 8001

spring:
  application:
    name: service-user
eureka:
  client:
    service-url:
      defaultZone: http://peer2:1112/eureka/, http://peer1:1111/eureka/
    healthcheck:
      enabled: true #使用health端点来代替心跳表明服务是否可用,反应到eureka server ui上服务的UP还是DOWN
  instance:
    lease-expiration-duration-in-seconds: 30 #租期更新时间间隔(默认30秒)
    lease-renewal-interval-in-seconds: 10 #租期更新时间间隔(默认30秒)
info:
  app:
    name: "@project.name@" #从pom.xml中获取
    description: "@project.description@"
    version: "@project.version@"
    spring-boot-version: "@project.parent.version@"

启动之后访问:http://localhost:8001

《Spring Colud》 Eureka 服务治理详解与高可用分布式搭建_第5张图片

《Spring Colud》 Eureka 服务治理详解与高可用分布式搭建_第6张图片

我们可以看到两个注册中心都有这个项目。至此,一个简单的高可用服务注册中心已经完成。
五、搭建服务消费者,
     我们将依赖前边的两个项目,高可用peer和服务提供者service-user来搭建服务消费者。
1、首先,我们在service-user中提供一个供注册的接口,如下:
/**
 * @author [email protected]
 * @date 2018/2/22 18:23
 */
@RestController
@RequestMapping("service/user")
public class UserController {
    Logger logger = LoggerFactory.getLogger(UserController.class);
    @Autowired
    private HttpServletRequest request;

    @RequestMapping(value = "public/login" , method = {RequestMethod.GET} ,produces = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity login(
            @RequestParam String account ,
            @RequestParam String password
    ){
        System.out.println(" request ::::::::: " +account+" == "+password);
        JSONObject jsonObject = new JSONObject();
        if("xuebin".equals(account) && "123456".equals(password)){
            jsonObject.put("status","success");
        }else {
            jsonObject.put("status","error");
        }
        return new ResponseEntity(jsonObject.toJSONString() , HttpStatus.OK);
    }
}
2、创建consumer项目,并注册到服务注册中心。
(1)、创建maven项目,命名为consumer。修改pom.xml文件如下:

    4.0.0
    consumer
    jar
    consumer
    http://maven.apache.org

    
        com.learning.ApplicationConsumer
        UTF-8
        UTF-8
        1.8
        1.8
        1.8
        1.8
    
    
        org.springframework.boot
        spring-boot-starter-parent
        1.5.10.RELEASE
    
    
        
        
            org.springframework.boot
            spring-boot-starter-web
        
        
        
            org.springframework.boot
            spring-boot-starter-test
            1.5.9.RELEASE
            test
        

        
        
             org.springframework.boot
            spring-boot-starter-actuator
        

        
            org.springframework.cloud
            spring-cloud-starter-eureka
            1.3.1.RELEASE
        

        
            junit
            junit
            4.12
            test
        
        
            org.springframework.boot
            spring-boot-test
            1.5.9.RELEASE
        
        
            org.springframework
            spring-test
            4.3.13.RELEASE
        
        
            junit
            junit
            4.12
        
    
    
        consumer
        
            
                org.springframework.boot
                spring-boot-maven-plugin
            
            
            
                org.apache.maven.plugins
                maven-surefire-plugin
                
                    true
                
            
        
    

(2)、创建配置文件application.yml,并设置相关参数如下:

server:
  port: 8201
spring:
  application:
    name: consumer
eureka:
  client:
    service-url:
      defaultZone: http://peer2:1112/eureka/, http://peer1:1111/eureka/
    healthcheck:
      enabled: true #使用health端点来代替心跳表明服务是否可用,反应到eureka server ui上服务的UP还是DOWN
  instance:
    lease-expiration-duration-in-seconds: 30 #租期更新时间间隔(默认30秒)
    lease-renewal-interval-in-seconds: 10 #租期更新时间间隔(默认30秒)
info:
  app:
    name: "@project.name@" #从pom.xml中获取
    description: "@project.description@"
    version: "@project.version@"
    spring-boot-version: "@project.parent.version@"

(3)、创建启动类,并设置为eureka客户端,详细代码如下:

@SpringBootApplication
@EnableEurekaClient
public class ApplicationConsumer {

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

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

(4)、创建UserController控制类并创建restful接口,提供rpc服务。详细代码如下:

/**
 * 用户控制类
 * @author [email protected]
 * @date 2018/2/22 17:52
 */
@Controller
@RequestMapping("/api/user")
public class UserController {
    Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserService userService;
    @ResponseBody
    @RequestMapping(value = {"/public/v1/login"}, method = {RequestMethod.POST, RequestMethod.GET}, produces = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity login(
            @RequestParam String account ,
            @RequestParam String password
    ){
        String user = userService.login(account , password);
        return new ResponseEntity(user , HttpStatus.OK);
    }
}

创建UserService接口:

/**
 * @author [email protected]
 * @date 2018/2/22 18:09
 */
public interface UserService {
    public String login(String account , String password);
}

创建UserServiceImpl接口实现类:

/**
 * @author [email protected]
 * @date 2018/2/22 18:11
 */
@Service
public class UserServiceImpl implements UserService {

    Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
    @Autowired
    private RestTemplate restTemplate;
    @Override
    public String login(String account, String password) {
        logger.debug(" 登陆 account=%s ; password=%s " , account , password);
        // 注意,这里我们使用的时服务注册中的服务名,不是ip。在分部署环境下,服务多了,管理ip会很混乱,使用项目名访问,简单明了。这也是出现服务治理的主要原因。
        String host = "http://SERVICE-USER/"; 
        return restTemplate.getForEntity(host+"service/user/public/login?account="
                +account+"&password="+password , String.class).getBody();
    }
}

(5)、启动consumer服务,继续查看peer1和peer2,我们会发现,consumer项目也存在与里边。

《Spring Colud》 Eureka 服务治理详解与高可用分布式搭建_第7张图片

(6)、访问登陆接口 http://localhost:8201/api/user/public/v1/login?account=xuebin&password=123456

访问成功,
六、创建多节点服务提供者
我们以上一节service-user服务提供者来搭建多节点,application-dev1.yml和application-dev2.yml。
application-dev_1.yml如下:
server:
  port: 8001

spring:
  application:
    name: service-user
eureka:
  client:
    service-url:
      defaultZone: http://peer2:1112/eureka/, http://peer1:1111/eureka/
#      defaultZone: http://localhost:1111/eureka/
    healthcheck:
      enabled: true #使用health端点来代替心跳表明服务是否可用,反应到eureka server ui上服务的UP还是DOWN
  instance:
    lease-expiration-duration-in-seconds: 30 #租期更新时间间隔(默认30秒)
    lease-renewal-interval-in-seconds: 10 #租期更新时间间隔(默认30秒)
info:
  app:
    name: "@project.name@" #从pom.xml中获取
    description: "@project.description@"
    version: "@project.version@"
    spring-boot-version: "@project.parent.version@"

application-dev_2.yml如下:

server:
  port: 8002

spring:
  application:
    name: service-user
eureka:
  client:
    service-url:
      defaultZone: http://peer2:1112/eureka/, http://peer1:1111/eureka/
    healthcheck:
      enabled: true #使用health端点来代替心跳表明服务是否可用,反应到eureka server ui上服务的UP还是DOWN
  instance:
    lease-expiration-duration-in-seconds: 30 #租期更新时间间隔(默认30秒)
    lease-renewal-interval-in-seconds: 10 #租期更新时间间隔(默认30秒)
info:
  app:
    name: "@project.name@" #从pom.xml中获取
    description: "@project.description@"
    version: "@project.version@"
    spring-boot-version: "@project.parent.version@"

编译打包之后,分别以如下方式启动该服务:

java -jar service-user.jar --spring.profiles.active=dev_1
java -jar service-user.jar --spring.profiles.active=dev_2

然后连续多次访问http://localhost:8201/api/user/public/v1/login?account=xuebin&password=123456接口,看控制台:

《Spring Colud》 Eureka 服务治理详解与高可用分布式搭建_第8张图片

Spring cloud封装实现的route类型filter,默认使用了ribbon对eureka 服务发现的负载均衡client。
通过日志我们可以看到,Ribbon作为后端负载均衡器,默认采用roundRobin方式轮询选择server。它一共提供了7种负载均衡策略:

策略名 策略声明 策略描述 实现说明
BestAvailableRule public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule 选择一个最小的并发请求的server 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server
AvailabilityFilteringRule public class AvailabilityFilteringRule extends PredicateBasedRule 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态
WeightedResponseTimeRule public class WeightedResponseTimeRule extends RoundRobinRule 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成status时,使用roubine策略选择server。
RetryRule public class RetryRule extends AbstractLoadBalancerRule 对选定的负载均衡策略机上重试机制。 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
RoundRobinRule public class RoundRobinRule extends AbstractLoadBalancerRule roundRobin方式轮询选择server 轮询index,选择index对应位置的server
RandomRule public class RandomRule extends AbstractLoadBalancerRule 随机选择一个server 在index上随机,选择index对应位置的server
ZoneAvoidanceRule public class ZoneAvoidanceRule extends PredicateBasedRule 复合判断server所在区域的性能和server的可用性选择server 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。

你可能感兴趣的:(AI:Spring,Boot,AI:Spring,Cloud)