springcloud的入门使用

1.什么是springcloud
–Spring cloud是一个基于Spring Boot实现的服务治理工具包,在微服务架构中用于管理和协调服务的。它是一系列框架的有序集合。它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。Spring并没有重复制造*,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来,通过Spring Boot风格进行再封装屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。
–springcloud的五大神兽
服务发现——Netflix Eureka
客服端负载均衡——Netflix Ribbon/Feign
服务网关——Netflix Zuul
断路器——Netflix Hystrix
分布式配置——Spring Cloud Config
springcloud主键结构:
springcloud的入门使用
2.springcloud的使用
–创建一个maven项目,在pom.xml中配置

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Finchley.SR1</spring-cloud.version>
<springboot.version>2.0.5.RELEASE</springboot.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${springboot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

3.springcloud–eureka注册中心
原理:
springcloud的入门使用
–项目中创建子模块,springcloud-eureka-7001
配置子模块pom.xml:

<dependencies>
        <!--springboot支持-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <!--Eureka服务端支持-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

配置application.yml:

server:
  port: 7001
eureka:
  instance:
    hostname: localhost
  client:
      registerWithEureka: false #是否要注册到eureka
      fetchRegistry: false #表示是否从Eureka Server获取注册信息
serviceUrl:
  defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #单机配置

主类,启动器:

@SpringBootApplication
@EnableEurekaServer//标识是eureka服务端
public class EnrekaServerApplication_7001 {
public static void main(String[] args) {
        SpringApplication.run(EnrekaServerApplication_7001.class);
    }
}

配置完毕之后,根据yml中配置的端口,访问:localhost:7001,进入页面
springcloud的入门使用
4.springcloud–provider服务提供者
项目中创建一个子模块:springcloud-provider-8001
子模块pom.xml中配置:

<dependencies>
<!--公共代码依赖-->
<dependency>
<groupId>cn.itsource.springcloud</groupId>
<artifactId>User_interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--springboot支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--eureka客户端支持 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>

配置application.yml:

server:
  port: 8001
spring:
  application:
     name: USER-PROVIDER #不要使用下划线
eureka:
  client:
    service-url:
      defaultZone: http://localhost:7001/eureka #告诉服务提供者要把服务注册到哪儿

入口,启动器:

@SpringBootApplication
@EnableEurekaClient //表示是eureka的客户端
public class UserProviderApplication_8001 {
public static void main(String[] args) {
        SpringApplication.run(UserProviderApplication_8001.class);
    }
}

Controller层测试:

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

//    @Autowired
   //    private IUserService userService;
@RequestMapping("/user/{id}") //user/1
public User getUser(@PathVariable("id") Long id) {

// 正常应该调用service获取用户,现在模拟一下
return new User(id, "zs");
    }
}

依据路径,访问 http://localhost:8001/provider/user/1 可以得到json数据
5.springcloud–consumer服务消费者
项目中创建一个子模块:springcloud-consumer-9001
配置子模块pom.xml:

<!--公共代码依赖-->
<dependency>
<groupId>cn.itsource.springcloud</groupId>
<artifactId>User_interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--springboot支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

配置application.yml

server:
  port: 9001
spring:
  application:
    name: USER_CONSUMER

入口类,启动器:

@SpringBootApplication
public class UserConsumerAppliction_9001 {
public static void main(String[] args) {
        SpringApplication.run(UserConsumerAppliction_9001.class);
    }
}

需要创建一个工具类,获取RestTemplate对象

@Configuration // <beans></beans>
public class CfgBean {

@Bean //<bean class="org.springframework.web.client.RestTemplate"></bean>
public RestTemplate getRestTemplate(){
return new RestTemplate();
    }
}

Controller层

@RestController
@RequestMapping("/consumer")
public class UserController {
//多个方法调用只需改一处就ok
public static  final String URL_PREFIX = "http://localhost:8001";
@Autowired
private RestTemplate restTemplate;

@RequestMapping("/user/{id}")
public User getUser(@PathVariable("id")Long id){
//调用远程服务 http请求
String url = URL_PREFIX+"/provider/user/"+id;
return restTemplate.getForObject(url,User.class );
    }
}

6.spring注册中心集群
如果只有一个注册中心服务器,会存在单点故障所以要集群,所以可以使用多个注册中心,如果某一个出现了问题,另一个立马替代其功能。
–拷贝一份springcloud-eureka-7002
映射hosts 模拟域名解析 C:\Windows\System32\drivers\etc
127.0.0.1 eureka-7001.com
127.0.0.1 eureka-7002.com
在两个控制中心的application.yml中配置:
springcloud-eureka-7001:

server:
  port: 7001
eureka:
  instance:
    hostname: eureka-7001.com
  client:
    registerWithEureka: false #是否要注册到eureka
    fetchRegistry: false #表示是否从Eureka Server获取注册信息
    serviceUrl:
      defaultZone: http://eureka-7002.com:7002/eureka/ #集群配置,如果有多个,有逗号分割,不要包含自己

springcloud-eureka-7002:

server:
  port: 7002
eureka:
  instance:
    hostname: eureka-7002.com
  client:
    registerWithEureka: false #是否要注册到eureka
    fetchRegistry: false #表示是否从Eureka Server获取注册信息
    serviceUrl:
      defaultZone: http://eureka-7001.com:7001/eureka/ #集群配置,如果有多个,有逗号分割,不要包含自己

上述配置,表示调用对方的控制中心
修改springcloud-provider-8001的application.yml的配置,使其接收两个控制中心的管理

server:
  port: 8001
spring:
  application:
name: user-provider #不要使用下划线
eureka:
  client:
    service-url:
      #defaultZone: http://localhost:7001/eureka #告诉服务提供者要把服务注册到哪儿
      defaultZone: http://eureka-7001.com:7001/eureka,http://eureka-7002.com:7002/eureka
instance:
  prefer-ip-address: true #显示客户端真实ip

集群配置之后,如果控制中心出现故障,服务提供者依然可以注册到其他的控制中心,而不会出现阻塞现象。
7.负载均衡的实现
为了提供并发量,有时同一个服务提供者可以部署多个。这个客户端在调用时要根据一定的负责均衡策略完成负载调用。
–实现方式一:Ribbon
Ribbon是Netflix发布的云中间层服务开源项目,主要功能是提供客户端负载均衡算法。Ribbon客户端组件提供一系列完善的配置项,如,连接超时,重试等。简单的说,Ribbon是一个客户端负载均衡器,我们可以在配置文件中列出load Balancer后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器,我们也很容易使用Ribbon实现自定义的负载均衡算法。
创建一个新的服务提供者:springcloud-provider-8002,并将该服务提供者注册到注册中心
在springcloud-consumer-9001中引入配置:
配置pom.xml

<!--公共代码依赖-->
<dependency>
    <groupId>cn.itsource</groupId>
    <artifactId>User_interface</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<!--springboot支持-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--eureka客户端,服务消费者也要从注册中心获取可用服务列表-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<!--客户端负载均衡实现 ribbon-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

配置yml:

server:
  port: 9001
eureka:
  client:
    registerWithEureka: false #不注册到Eureka,不在注册中心显示
    service-url:
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka-7001.com:7001/eureka,http://eureka-7002.com:7002/eureka

新的入口,启动器:

@SpringBootApplication
@EnableEurekaClient
public class UserConsumerApplicaton_9001 {
public static void main(String[] args) {
        SpringApplication.run(UserConsumerApplicaton_9001.class);
    }
}

在工具类上添加注解,开启负载均衡

@Configuration
public class CfgBean {

@Bean
 @LoadBalanced //开启负载均衡
public RestTemplate getRestTemplate(){
return  new RestTemplate();
    }
}

Controller层:

@RestController
@RequestMapping("/consumer")
public class UserController {
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/user/{id}")
    public User getUser(@PathVariable("id")Long id){
        String url = "http://USER-PROVIDER/provider/user/"+id;
        return restTemplate.getForObject(url, User.class);
    }
}

这样就可以实现,每次访问的时候,能够间隔的访问不同的服务端
–实现方式二:Feign
前面的可以发现当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且显得好傻。
Feign是一个声明式的Web Service(RPC框架)客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。Feign整合了Ribbon(负载均衡)和Hystrix(断路器)(关于Hystrix我们后面再讲),可以让我们不再需要显式地使用这两个组件。
总起来说,Feign具有如下特性:
1.可插拔的注解支持,包括Feign注解和JAX-RS注解;
2.支持可插拔的HTTP编码器和解码器;
3.支持Hystrix和它的Fallback;
4.支持Ribbon的负载均衡;
5.支持HTTP请求和响应的压缩。
这看起来有点像我们springmvc模式的Controller层的RequestMapping映射。这种模式是我们非常喜欢的。Feign是用@FeignClient来映射服务的。
创建新的服务消费者:springcloud-consumer-9002
配置pom.xml:

<dependencies>
<!--公共代码依赖-->
<dependency>
<groupId>cn.itsource.springcloud</groupId>
<artifactId>User_interface</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

<!--springboot支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

<!--eureka客户端,服务消费者也要从注册中心获取可用服务列表-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

<!--feign的支持-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>

配置yml:

server:
  port: 9002
eureka:
  client:
    registerWithEureka: false #不注册到Eureka,不在注册中心显示
    service-url:
      #defaultZone: http://localhost:7001/eureka
      defaultZone: http://eureka-7001.com:7001/eureka,http://eureka-7002.com:7002/eureka

入口,启动器:

@SpringBootApplication
@EnableFeignClients(basePackages = "cn.itsource")
@EnableEurekaClient
public class UserConsumerApplication_9002 {

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

创建一个接口,用来访问服务提供者的路径,value 表示 服务提供者的yml中name的值

@FeignClient(value = "USER-PROVIDER")
@RequestMapping("/provider")
public interface UserCilent {
        @RequestMapping("/user/{id}")
        User getUser(@PathVariable("id")Long id);
}

Controller层:

@RestController
@RequestMapping("/consumer")
public class UserController {
    @Autowired
    private UserCilent userCilent;
    @RequestMapping("/user/{id}")
    public User getUser(@PathVariable("id")Long id){
        return userCilent.getUser(id);
    }
}