1、微服务的来历
微服务是从SOA服务架构演变过来的,将比SOA服务架构的粒度更细,各个模块之间分工更加明确,让其可以更专注于做某一件事情,而且各个服务之间是可以独立部署运行的,互相不影响。
2、何为微服务治理?
在传统的RPC服务调用中,各个服务与服务之间的依赖复杂,而在微服务架构中需要管理这些复杂的依赖关系,从而实现对服务的调用,负载均衡,容错等,实现服务的注册和发现。
注册中有Eureka、Consul、Zokeerper
3、单机配置
配置注册中心:
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
spring:
application:
name: eureka-server
server:
port: 8100
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
提供服务端:
@EnableEurekaClient
@SpringBootApplication
public class EurekaProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaProviderApplication.class, args);
}
}
@RestController
@RequestMapping("user")
public class UserController {
@Value("${server.port}")
private String serverPort;
@RequestMapping("/getUser")
public String getUser() {
return "this is user service,端口号为:" + serverPort;
}
}
spring:
application:
name: eureka-provider
server:
port: 8010
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka/
fetch-registry: false
register-with-eureka: false
消费端:
@EnableEurekaClient
@SpringBootApplication
public class EurekaConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaConsumerApplication.class, args);
}
}
@RestController
@RequestMapping("order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/getOrder")
public String getOrder() {
String memberUrl = "http://eureka-provider/user/getUser";
String result = restTemplate.getForObject(memberUrl, String.class);
System.out.println("用户服务调用订单服务,result:" + result);
return result;
}
}
spring:
application:
name: eureka-consumer
server:
port: 8001
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka/
register-with-eureka: false
fetch-registry: false
4、集群高可用配置
注册中心修改配置:
service-url:
#配置多个server,中间用逗号
defaultZone: http://localhost:8300/eureka/,http://localhost:8400/eureka/
#集群配置时候需要注册自己到注册中心
register-with-eureka: true
#集群配置时候需要从注册中心检索出服务
fetch-registry: true
服务提供端:
service-url:
#将服务注册到多个注册中心中
defaultZone: http://localhost:8200/eureka/,http://localhost:8300/eureka/,http://localhost:8400/eureka/
fetch-registry: true
register-with-eureka: true
消费端修改配置同理服务提供端
5、Eureka的自我保护机制
现象:
为什么当有EurekaClient宕机时,但是在注册中心还是能看见对应注册的服务?这就是由于Eureka的自我保护机制造成的。
作用:
为了防止由于网络原因不通而将对应的Client给注销。Eureka默认时间是90秒。
PS:默认情况下,Eureka会在一定时间内(默认心跳时间间隔30秒,而服务器在收到最后一个心跳后等待时间默认为90s)没有收到客户端的心跳,EurekaServer则会将该服务给注销,当出现丢失的client过多,达到一个设定的阀值时,(比如在网络故障情况下,实际上服务是可以正常运行的),就会开启自我保护机制,并且持续到15分钟。
阀值计算:
源码:
protected void initEurekaServerContext() throws Exception {
//省略代码。。。
EurekaServerContextHolder.initialize(this.serverContext);
log.info("Initialized server context");
int registryCount = this.registry.syncUp();
//计算阀值
this.registry.openForTraffic(this.applicationInfoManager, registryCount);
EurekaMonitors.registerAllStats();
}
protected void updateRenewsPerMinThreshold() {
this.numberOfRenewsPerMinThreshold = (int)((double)this.expectedNumberOfClientsSendingRenews * (60.0D / (double)this.serverConfig.getExpectedClientRenewalIntervalSeconds()) * this.serverConfig.getRenewalPercentThreshold());
}
相关配置:
Server端:
#是否开启自我保护机制 ,默认是true
eureka.server.enable-self-preservation: true
#检查失效服务的时间,并移除列表,默认该配置是 60s
eureka.server.eviction-interval-timer-in-ms: 6000
#默认的自我保护系数
eureka.server.renewal-percent-threshold: 0.85
Client端:
#eureka客户端向eureka服务器发送心跳的时间间隔,默认该配置是 30s
eureka.instance.lease-renewal-interval-in-seconds: 30
#eureka服务器在接收到client最后一个心跳之后等待的时间,然后才能从列表中删除此实例,默认该配置是 90s
eureka.instance.lease-expiration-duration-in-seconds: 90