spring cloud 开发分布式的工具集
微服务简介:
微服务是以开放小型服务的方式来开发一个独立的应用系统的。其中每一个小型项目都运行在自己的进程中,并经常采用HTTP资源API这样轻量的机制来相互通信,这些服务围绕业务功能进行构建,并通过全自动的部署机制来进行独立部署。这些微服务可以用不同的语言来编写,并且可以使用不同的数据存储技术。对这些微服务我们仅做最低限度的几种管理
微服务特性:
应具备以下特征
1.每个微服务课独立运行在自己的进度量
2.一系列独立运行的微服务共同创建起整个系统
3.每个服务为独立的业务开发,一个微服务只关注某个特定的功能,例如订单管理,用户管理等
4.微服务之间通过一些轻量的通信机制进行通信,例如通过REST API进行调用
5.可以使用不同的语言与数据存储技术
6.全自动的部署机制
微服务架构的挑战
1. 运维要求较高
更多的服务意味着更多的运维投入,在单体架构中,只需要保证一个应用的正常运行;而在微服务中,需要保证几十个甚至几百个服务的正常运行与协作,这给项目的运维带来了很大的挑战
2. 分布式特有的复杂性
使用微服务构建的是分布式系统。对于一个分布式系统,系统容错,网络言辞,分布式事务等都给我们带来的很大的挑战
3. 接口调整成本高
微服务之间通过接口进行通信,如果修改某个微服务的API,可能所有使用了该接口的微服务都需要做调整
4. 重复劳动
很多服务可能都会使用相同的功能,而这个功能并没有达到分解为一个微服务的程度,这个时候,可能各个服务都用到这个功能,从而导致代码重复。
SpringCoud 开发分布式的工具集
服务注册和发现
服务消费者:调用别的微服务的微服务
服务发现者:提供API的微服务
服务注册表
包括服务消费者和服务提供者的IP和端口
Eureka服务端代码
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
application.yml
server:
port: 8761
eureka:
client:
register-with-eureka: false #是否注册到别的eureka
fetch-registry: false #是否要合并到别的eureka中去
在启动类上面加
@EnableEurekaServer
服务提供者,
这个微服务需要注册到eureka上.而类似的注解后面就不说了
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
application.yml
server:
port: 7900
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: microservice-provider-user
启动类上面加
@EnableDiscoveryClient
Controller
package com.ldgx.eshop.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value="/demo")
public class DemoController {
@RequestMapping(value="/dd")
public String dd() {
return "user original time";
}
}
服务消费者使用ribbon
1. ribbon定义在启动类上面定义
@Bean
@LoadBalanced //使restTemplate变成ribbon,带有负载均衡的能力
public RestTemplate restTemplate(){
return new RestTemplate();
}
2. ribbon使用
package com.ldgx.eshop.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class UseDemoController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/demo")
public String useDemo() {
return restTemplate.getForObject("http://microservice-provider-user/demo/dd", String.class);//参数1使eureka的service-id,是个虚拟主机名,可以用eureka.instance.secure.virtual-host-name定义,如果不是https的,就用eureka.instance.virtual-host-name
}
}
3. Feign使用
pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
接口
package com.ldgx.eshop.feign;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
@FeignClient("MICROSERVICE-PROVIDER-USER")
public interface UserFeignClient {
@RequestMapping(value="/demo/dd")//和服务提供者的url完全一样
public String dd();
}
controller
package com.ldgx.eshop.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.ldgx.eshop.feign.UserFeignClient;
@RestController
public class DemoController {
@Autowired
private UserFeignClient userFeignClient;//注入feign接口
@RequestMapping("/demo")
public String demo() {
System.out.println("=demo=============");
return userFeignClient.dd();
}
}
启动类增加注解
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
@FeignClient(name="microservice-provider-user")
public interface UserFeignClient{
@RequestMapping(value="/{id}",method=RequestMethod.GET)
public User getById(@PathVariable("id")Long id);
}
4. 断路器
在主方法中
@EnableCircuitBreaker或者@EnableHystrix
在service中
@HystrixCommand(fallbackMethod="hiError")
短路后,会调用hiError方法,这个方法的参数和返回值要和原方法一样。
5. Foreign hystrix支持
@FeignClient(name="microservice-provider-user",fallback=FeignClientFallback.class
public interface ...
@Component
class FeignClientFallback implements UserFeignClient{
//复写原方法
}