一. 服务注册与发现
- 服务注册:服务提供者将服务的信息(IP、端口、协议等)登记到注册中心
- 服务发现:服务消费者根据一定策略从注册中心的服务列表选取一个服务
1.eureka
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
eureka:
instance:
hostname: eureka7003.com #eureka服务端的实例名称
instance-id: payment8001
prefer-ip-address: true
client:
register-with-eureka: false #false表示不向注册中心注册自己。
fetch-registry: false #false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
service-url:
#集群指向其它eureka
#defaultZone: http://eureka7002.com:7002/eureka/
#单机就是7001自己
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
#server:
#关闭自我保护机制,保证不可用服务被及时踢除
#enable-self-preservation: false
#eviction-interval-timer-in-ms: 2000
2.zookeeper
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
</dependency>
spring:
application:
name: cloud-zoo-consumer-order
cloud:
zookeeper:
connect-string: 192.168.10.58:2181
3.consul
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
spring:
application:
name: consul-payment-provider
cloud:
consul:
host: 192.168.10.58
port: 8500
discovery:
service-name: ${spring.application.name}
主启动类添加注解开启服务注册与发现
@EnableDiscoveryClient
@SpringBootApplication
4.Nacos
二. 负载均衡
将请求压力分配到多个服务器,来提高服务器的性能、可靠性
1.ribbon
负载均衡策略
- RandomRule:随机
- RoundRobinRule:轮询,按顺序
- RetryRule:选择server不成功则在规定时间内一直重试
- BestAvailableRule:选并发量最低的server
- AvailabilityFilteringRule:过滤掉老失败或并发量达到阈值的
- ResponseTimeWeightedRule:响应快的权重高,被选到的概率高
- ZoneAvoidanceRule:综合判断server所在区域的性能
配置负载均衡
//注意不能和主启动类放在一个包下,所以另建一个包存放
@Configuration
public class Myrule {
@Bean
public IRule initRule() {
return new RandomRule(); //随机
}
}
主启动类添加注解加载配置
@RibbonClient(name = "cloud-payment-service", configuration = Myrule.class)
三. 服务调用
针对每个微服务自行封装所依赖服务的调用,常用方式有
1.Ribbon + RestTemplate
RestTemplate调用,使用 xxxforObject 或 xxxforEntity
@RestController
public class OrderController {
public static final String PAYMENT_URL = "http://localhost:8001";
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/create")
public CommonResult<Payment> create(Payment payment) {
return restTemplate.postForObject(PAYMENT_URL + "payment/create", payment, CommonResult.class);
}
@GetMapping("/consumer/payment/get/{id}")
public CommonResult<Payment> getPayment(@PathVariable("id") Long id) {
return restTemplate.getForObject(PAYMENT_URL + "payment/get/" + id, CommonResult.class);
}
}
2.Dubbo(RPC)
RPC调用,使用@Reference注解
@Service
public class UserService {
@Reference
ProductService productService; //注入其他服务
...
}
3.OpenFeign(内部集成ribbon负载均衡+hsytrix熔断)
OpenFeign调用,启动类添加注解,使用@FeignClient指定要调用的提供方服务名
@EnableFeignClients
@FeignClient(value = "CLOUD-PAYMENT-SERVICE") //提供方服务名
public interface Service {
@GetMapping(value = "/payment/get/{id}")
Response<Payment> getPaymentById(@PathVariable("id") Long id);
}
超时设置
ribbon:
#指的是建立连接所用的时间,适用于网络状况正常的情况下,两端连接所用的时间
ReadTimeout: 5000
#指的是建立连接后从服务器读取到可用资源所用的时间
ConnectTimeout: 5000
logging:
level:
ml.ytooo.feignservice.Service: debug
配置日志
@Configuration
public class FeignLogConfig {
@Bean
public Logger.Level getLevel() {
return Logger.Level.FULL;
}
}
四. 服务治理(限流、熔断、降级)
- 服务限流:配置服务承载能力,只允许系统能够承受的访问量进来,超出的会被丢弃
- 服务熔断:下游服务故障,暂时切断,局部牺牲,保全整体
- 服务降级:从服务负载考虑,停到一些非核心功能的服务,并给客户端返回友好提示
1. Hsytrix
降级
@EnableCircuitBreaker
针对单个核心业务的方法配置独立的降级规则
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOut_Handler", commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
value = "3000")
})//访问接口调用此方法如果超时3s,则调用回调方法
public String paymentInfo_TimeOut(Integer id) {
return "线程池: " + Thread.currentThread().getName() + " paymentInfo_TimeOut,id: " + id + "\t" + "O(∩_∩)O哈哈~" + " 耗时(秒): " + time;
}
//超时回调方法
public String paymentInfo_TimeOut_Handler(Integer id) {
return "线程池: " + Thread.currentThread().getName() + " paymentInfo_TimeOut_Handler,id: " + id + "\t" + "o(╥﹏╥)o";
}
针对普通的其他业务配置全局降级规则
@RestController
@Slf4j
@DefaultProperties(defaultFallback = "globle",commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",
value = "3000")
})
public class Controller {
@HystrixCommand
@GetMapping("/timeout/{id}")
public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
String result = feignService.paymentInfo_TimeOut(id);
log.info("*****result: " + result);
return result;
}
public String globle() {
return "全局";
}
}
熔断
//=====服务熔断
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = { //
@HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否开启断路器
@HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 请求次数
@HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 时间窗口期
@HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失败率达到多少百分百后跳闸
})
public String paymentCircuitBreaker(@PathVariable("id") Integer id)
{
if(id < 0)
{
throw new RuntimeException("******id 不能负数");
}
String serialNumber = IdUtil.simpleUUID();
return Thread.currentThread().getName()+"\t"+"调用成功,流水号: " + serialNumber;
}
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) //熔断后降级方法
{
return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~ id: " +id;
}
2. Sentinel
五. 服务网关
请求统一发送到网关,由网关转发,解决跨域、权限等问题
1. GateWay
动态路由
spring:
application:
name: cloud-gateaway-gateaway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh #路由id,没有固定规则,但要求统一
#uri: http://localhost:8001 匹配集群服务1的地址
uri: lb://cloud-payment-service #匹配提供方服务名
predicates: #断言,配置的属性可以作为转发请求的触发条件
- Path=/payment/get/** #匹配需要的转发请求
- After=2021-02-21T15:51:37.485+08:00[Asia/Shanghai] #这个时间之后才能转发请求
- Cookie=name,value #请求需要携带指定Cookie才能访问
- id: payment_routh
#uri: http://localhost:8002 匹配集群服务2的地址
uri: lb://cloud-payment-service #如果匹配的是服务名,则网关会实现负载均衡
predicates:
Path=/payment/lb/**
自定义过滤器,可以对请求转发前进行处理
filters:
- AddRequestParamter=rowid,1024
@Component
@Slf4j
public class GatewayLogFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("=====================进入全局过滤器=====================");
String name = exchange.getRequest().getQueryParams().getFirst("name");
if (null == name) {
exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
六. 分布式配置中心
对大量不同服务提供一套集中式、动态的外部总配置
1.SpringCloud Config
服务端
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
spring:
application:
name: cloud-config-center
cloud:
config:
server:
git:
uri: https://github.com/youdmeng/cloud-config
search-paths:
- cloud-config
label: master
@EnableConfigServer
@SpringBootApplication
客户端
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-client</artifactId>
</dependency>
spring:
application:
name: cloud-condig-client
cloud:
config:
label: master # 分支
name: config # 配置文件名称
profile: dev # 版本
uri: http://127.0.0.1:3344 # config服务端地址