微服务SpringCloud

个人博客,欢迎访问:www.live4bug.com

1.Eureka注册中心

1.1 注册服务端Eureka Server

引入依赖,其中已经包含了spring-cloud的依赖,无需再引入。


    org.springframework.cloud
    spring-cloud-starter-netflix-eureka-server
 

相应的配置文件:

server:
  port: ${PORT:50101}
spring:
  application:
    name: xc-govern-center
eureka:
  client:
    register-with-eureka: true # 服务注册,是否将自己注册到Eureka服务中
    fetch-registry: true # 服务发现,是否从Eureka中获取注册信息
    service-url: # Eureka客户端与Eureka服务端的交互地址,高可用状态配置对方的地址,单机状态配置自己(如果不配置则默认本机8761端口)
      defaultZone: ${EUREKA_SERVER:http://eureka02:50102/eureka/}
  server:
    enable-self-preservation: false # 是否开启自我保护,本地测试不开启,实际要开启
    eviction-interval-timer-in-ms: 60000 # 服务注册表清理间隔,默认60*1000毫秒
  instance:
    hostname: ${EUREKA_DOMAIN:eureka01} # 主机名

其中注意,defaultZone为配置的注册中心的地址(即,需要向哪里进行注册),此处的eureka02对应的是另一配置的主机名(即另一配置的instance-hostname:eureka02),而为了使该主机名能够被正确解析,需要在本机的System32-drivers-etc-host文件中进行配置,如:

127.0.0.1   eureka01
127.0.0.1   eureka02    

同时,为了启动的灵活性,可以在启动时配置VM options环境参数,如下:

-DPORT=50101 -DEUREKA_DOMAIN=eureka01 -DEUREKA_SERVER=http://eureka02:50102/eureka/ 

最后,在启动类标识注解@EnableEurekaServer,注明该工程为注册中心服务端。

1.2 注册客户端 Eureka Client

引入依赖,其中已经包含了spring-cloud的依赖,无需再引入。

注意,此处依赖不要引错!不是spring-cloud-netflix-eureka-client !!!

    org.springframework.cloud
    spring-cloud-starter-netflix-eureka-client

    
据说没有spring-boot-starter-web会注册失败,未验证。

    org.springframework.boot
    spring-boot-starter-web
            

相应的配置文件:

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: ${EUREKA_SERVER:http://localhost:50101/eureka/}
  instance:
    prefer-ip-address: true # 将自己的ip注册到eureka服务中
    ip-address: ${IP_ADDRESS:127.0.0.1}
    instance-id: ${spring.application.name}:${server.port} # 指定实例id

最后,在启动类标识注解@EnableEurekaClient,注明该工程为注册中心客户端。此处,推荐使用@EnableDiscoveryClient,异同请自己百度。

2 Ribbon负载均衡

2.1 服务端/客户端负载均衡的概念

服务端负载均衡:负载均衡器维护一份服务列表。硬件设备实现,如F5,Array等;软件实现,如LVS、Nginx等。

客户端负载均衡:客户端维护一份服务列表,例如,Ribbon从注册中心获取服务列表,Ribbon根据负载均衡算法直接请求到具体的微服务(中间省去了负载均衡服务)。

两者区别:服务端负载均衡,是客户端发送请求后的接收端(即服务端)来维护服务列表,先接收信息,再根据一定的算法对列表中的项目(各微服务)进行转发,实现服务端负载均衡。客户端负载均衡:是发起者(客户端)自己维护一份服务列表(比如像Ribbon这种,从注册中心获取服务列表),然后再根据算法对列表中的项目(各微服务)进行调用

2.2 Ribbon负载均衡的实现

Spring Cloud引入Ribbon配合 restTemplate 实现客户端负载均衡。Java中远程调用的技术有很多,如: webservice、socket、rmi、Apache HttpClient、OkHttp等,互联网项目使用基于http的客户端较多,这里使用OkHttp实现。

首先,在客户端(发起者)添加Ribbon以及远程调用技术的依赖:由于依赖了spring-cloud-starter-eureka,会自动添加spring-cloud-starter-ribbon依赖。


    org.springframework.cloud
    spring-cloud-starter-netflix-ribbon
    2.0.1.RELEASE

    

    com.squareup.okhttp3
    okhttp

然后,添加配置文件:

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: ${EUREKA_SERVER:http://localhost:50101/eureka/}
  instance:
     prefer-ip-address: true # 将自己的ip注册到eureka服务中
     ip-address: ${IP_ADDRESS:127.0.0.1}
     instance-id: ${spring.application.name}:${server.port} # 指定实例id
ribbon:
  MaxAutoRetries: 2 #最大重试次数,当Eureka中可以找到服务,但是服务连不上时将会重试
  MaxAutoRetriesNextServer: 3 #切换实例的重试次数
  OkToRetryOnAllOperations: false  #对所有操作请求都进行重试,如果是get则可以,如果是post,put等操作没有实现幂等的情况下是很危险的,所以设置为false
  ConnectTimeout: 5000  #请求连接的超时时间
  ReadTimeout: 6000 #请求处理的超时时间

为了一会儿实现远程调用,这时要添加相应的Bean,注意因为调用时就要执行负载均衡策略,所以在此添加@LoadBalanced注解。

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {

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

完成单元测试代码:

@Autowired
RestTemplate restTemplate; 

@Test
public void testRibbon(){
    //在注册中心注册的服务名称
    String serviceId = "XC-SERVICE-MANAGE-CMS";
    for (int i = 0;i < 7;i++){
        //执行远程调用方法
        ResponseEntity forEntity = restTemplate
            .getForEntity("http://" + serviceId + "/get", CmsPage.class);
        CmsPage cmsPage = forEntity.getBody();
        System.out.println(cmsPage);
    }

}

进行测试:先运行注册中心项目;再运行需要被调用(服务端)的项目,通过不同端口号运行多个实例,观察注册中心,查看这些实例是已经否完成了注册;运行测试类,进行测试。

注意,添加@LoadBalanced注解后,restTemplate会走LoadBalancerInterceptor拦截器,此拦截器中会通过 RibbonLoadBalancerClient查询服务地址,可以在此类打断点观察每次调用的服务地址和端口,两个cms服务会轮 流被调用。

最初在写测试代码时一直在思考,“远程调用时的服务列表是怎么从注册中心获取的?”。后来想明白了,要想执行负载均衡,该项目本身必须要通过Eureka在注册中心进行“发现”,也就是application.yml中配置的eureka各参数,这样,自己就和注册中心有了关联,就可以获取到服务列表(很多的 “XC-SERVICE-MANAGE-CMS” 实例)。这时,restTemplate.getForEntity()方法中的http后面的服务名称(serviceId,即 “XC-SERVICE-MANAGE-CMS”) 就会去注册中心寻找相应的地址,完成远程请求。

2.3 Feign远程调用

Spring Cloud引入 Feign并且集成了Ribbon实现客户端负载均衡调用。

首先,引入Feign的依赖,这里因为Feign集成了Ribbon,所以可以把之前的Ribbon依赖注释掉。


    org.springframework.cloud
    spring-cloud-starter-openfeign

然后,建立一个Feign的接口,用于远程调用。注意,这里接口的url,请求类型,返回值类型都要和正常请求一样,例如@PathVariable("xxx") , @RequestParam("xxx")都一定要写全。返回值为复杂对象时,其类型必须有无参构造函数。

import com.xuecheng.framework.domain.cms.CmsPage;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

@FeignClient(value = "XC-SERVICE-MANAGE-CMS")
public interface CmsFeignClient {

    @GetMapping("/cms/page/get/{id}")
    public CmsPage findCmsPageById(@PathVariable("id") String id);
}

启动类,一定要加上 @EnableFeignClients 注解

最后,编写测试类。

@Autowired
CmsFeignClient cmsFeignClient;

@Test
public void testFeign(){
    CmsPage cmsPage = cmsFeignClient.findCmsPageById("5a754adf6abb500ad05688d9");
    System.out.println(cmsPage);
}

启动顺序和上一节类似。

你可能感兴趣的:(微服务SpringCloud)