<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
server.port=9000
#配置eurekaserver
eureka.instance.hostname=localhost
#是否将自己注册到注册中心
eureka.client.register-with-eureka=true
#是否从eureka中获取注册信息
eureka.client.fetch-registry=false
#配置暴露给Eureka Client的请求地址
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka/
@EnableEurekaServer
然后能正常访问http://localhost:9000/就说明没问题
简单producter、consumer
spring:
application:
name: eureka-server
server:
port: 9000 #端口
#配置eureka server
eureka:
client:
register-with-eureka: false #是否将自己注册到注册中心
fetch-registry: true #是否从eureka中获取注册信息
service-url: #配置暴露给Eureka Client的请求地址
defaultZone: http://localhost:9000/eureka/
server:
enable-self-preservation: false #关闭自我保护
eviction-interval-timer-in-ms: 4000 #剔除服务间隔
server:
port: 9001 #端口
spring:
application:
name: service-product #服务名称
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/shop?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
username: root
password: 123456
jpa:
database: MySQL
show-sql: true
open-in-view: true
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/ #多个eurekaserver之间用,隔开
instance:
prefer-ip-address: true #使用ip地址注册
server:
port: 9002 #端口
spring:
application:
name: service-order #服务名称
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/shop?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8
username: root
password: 123456
jpa:
database: MySQL
show-sql: true
open-in-view: true
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
provider、consumer可以不需要配置启动类

简单例子
@Bean
public RestTemplate restTemplate() { return new RestTemplate(); }
@RestController
@RequestMapping("/order")
public class OrderController {
//注入restTemplate对象
@Resource
private RestTemplate restTemplate;
/**
* 注入DiscoveryClient : springcloud提供的获取原数组的工具类 调用方法获取服务的元数据信息
*/
@Autowired
private DiscoveryClient discoveryClient;
/**
* 参数:商品id
* 通过订单系统,调用商品服务根据id查询商品信息
* 1.需要配置商品对象
* 2.需要调用商品服务
* 使用java中的urlconnection,httpclient,okhttp
*/
@RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
public Product findById(@PathVariable Long id) {
//调用discoveryClient方法
//已调用服务名称获取所有的元数据
List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
//获取唯一的一个元数据
ServiceInstance instance = instances.get(0);
//根据元数据中的主机地址和端口号拼接请求微服务的URL
Product product = null;
//如何调用商品服务?
product = restTemplate.getForObject("http://" + instance.getHost() + ":" + instance.getPort() + "/product/1", Product.class);
return product;
}
}
上面是生产者,下面的消费者:
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService productService;
@Value("${server.port}")
private String port;
@Value("${spring.cloud.client.ip-address}") //spring cloud 自动的获取当前应用的ip地址
private String ip;
@RequestMapping(value = "/{id}",method = RequestMethod.GET)
public Product findById(@PathVariable Long id) {
Product product = productService.findById(id);
product.setProductName("访问的服务地址:"+ip + ":" + port);
return product;
}
@RequestMapping(value = "",method = RequestMethod.POST)
public String save(@RequestBody Product product) {
productService.save(product);
return "保存成功";
}
}
order在9002,product在9001

高可用
集群相互注册,复制值configuration,一个port9000zone8000,另一port8000zone9000
eureka:
client:
register-with-eureka: true #是否将自己注册到注册中心
fetch-registry: true #是否从eureka中获取注册信息
service-url: #配置暴露给Eureka Client的请求地址
defaultZone: http://localhost:8000/eureka/
server:
enable-self-preservation: false #关闭自我保护
eviction-interval-timer-in-ms: 4000 #剔除服务间隔


微服务注册到多个集群上。避免其中一个down掉后另一个无法得知服务状态
#配置Eureka
eureka:
client:
service-url: #多个eurekaserver之间用,隔开
defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
# instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心中注册服务id
#lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
# lease-expiration-duration-in-seconds: 10 #续约到期的时间
优化、用ip注册:
#配置Eureka
eureka:
client:
service-url: #多个eurekaserver之间用,隔开
defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心中注册服务id
优化:心跳间隔,续约到期时间
(如果Eureka在10秒内检测不到我,那么就说明我挂了,所以我每5秒就向Eureka发送一次心跳)
#配置Eureka
eureka:
client:
service-url: #多个eurekaserver之间用,隔开
defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
instance-id: ${spring.cloud.client.ip-address}:${server.port} #向注册中心中注册服务id
lease-expiration-duration-in-seconds: 10 #续约到期的时间
lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
优化:关闭自我保护,剔除服务间隔
#配置eureka server
eureka:
client:
register-with-eureka: false #是否将自己注册到注册中心
fetch-registry: false #是否从eureka中获取注册信息
service-url: #配置暴露给Eureka Client的请求地址
defaultZone: http://localhost:9000/eureka/
server:
enable-self-preservation: false #关闭自我保护
eviction-interval-timer-in-ms: 4000 #剔除服务间隔
Springboot自动装载
@Data
public class User {
private String username;
private Integer age;
}
public class UserConfiguration {
@Bean
public User getUser() {
User user = new User();
user.setAge(23);
user.setUsername("腼腆Hold");
return user;
}
}
public class UserImportSelector implements ImportSelector {
//@Configuration
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//获取配置类的名称
return new String[]{UserConfiguration.class.getName()};
}
}
@Retention(RetentionPolicy.RUNTIME) //什么时候运行
@Documented //这个注解应该被 javadoc工具记录
@Target(ElementType.TYPE) //配置到什么地方
@Import(UserImportSelector.class) //自动加载selector
public @interface EnableUserBean {
}
然后测试
@EnableUserBean
public class TestApplication {
/**
* --> EnableUserBean --> UserImportSelector --> UserConfiguration --> User
* @param args
*/
public static void main(String[] args) {
//获取spring容器
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestApplication.class);
User bean = ac.getBean(User.class);
System.out.println(bean);
}
}
ImportSelector接口是Spring导入外部配置的核心接口,在SpringBoot的自动化配置和@EnableXXX中气到决定性作用。(P25自动配置原理)

Ribbon
负载均衡器,有助于控制HTTP和TCP客户端行为。一般Eureka都是配合Ribbon使用的
服务调用:在创建RestTemplate时,声明@LoadBalanced,使用restTemplate时就不需要再拼接微服务的URL了,以请求的服务名来代替(注意不要自定义instance-id)
#配置eureka server
eureka:
client:
register-with-eureka: false #是否将自己注册到注册中心
fetch-registry: false #是否从eureka中获取注册信息
service-url: #配置暴露给Eureka Client的请求地址
defaultZone: http://localhost:9000/eureka/
server:
enable-self-preservation: false #关闭自我保护
eviction-interval-timer-in-ms: 4000 #剔除服务间隔
#配置Eureka
eureka:
client:
service-url: #多个eurekaserver之间用,隔开
defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
lease-expiration-duration-in-seconds: 10 #续约到期的时间
lease-renewal-interval-in-seconds: 5 #向注册中心中注册服务id
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:9000/eureka/,http://localhost:8000/eureka/
instance:
prefer-ip-address: true #使用ip地址注册
使用consumer:
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
//注入restTemplate对象
@Resource
private RestTemplate restTemplate;
/**
* 基于ribbon的形式调用远程微服务
* 1.使用@LoadBalanced声明RestTemplate
* 2.使用服务名称替换ip地址
*/
@RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
public Product findById(@PathVariable Long id) {
Product product = null;
product = restTemplate.getForObject("http://service-product/product/1", Product.class);
return product;
}
使用producer:
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService productService;
@Value("${server.port}")
private String port;
@Value("${spring.cloud.client.ip-address}") //spring cloud 自动的获取当前应用的ip地址
private String ip;
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public Product findById(@PathVariable Long id) {
Product product = productService.findById(id);
product.setProductDesc("访问的服务地址:" + ip + ":" + port);
return product;
}
}
负载均衡:把一个典型的客户端负载均衡器,Ribbon会获取服务的所有地址,根据内部的负载均衡算法,获取本次请求的有效地址。
单机测试:只需复制configuration,改端口模拟运行两个producer,那么Eureka就会显示有两个同名的服务。
只要consumer配置了@LoadBalanced,默认可无需多做配置,它自动完成负载。(默认是轮循方式的)
如何修改负载策略?
#修改ribbon的负载均衡策略,服务名 - ribbon - NFLoadBalancerRuleClassName: 策略
service-product:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
com.netflix.loadbalancer.RoundRobinRule :以轮询的方式进行负载均衡。
com.netflix.loadbalancer.RandomRule :随机策略
com.netflix.loadbalancer.RetryRule :重试策略。
com.netflix.loadbalancer.WeightedResponseTimeRule :权重策略。会计算每个服务的权重,越高的被调用的可能性越大。
com.netflix.loadbalancer.BestAvailableRule :最佳策略。遍历所有的服务实例,过滤掉故障实例,并返回请求数最小的实例返回。
com.netflix.loadbalancer.AvailabilityFilteringRule :可用过滤策略。过滤掉故障和请求数超过阈值的服务实例,再从剩下的实力中轮询调用。
请求重试:实现访问失败的话重试一次,若不成功则切换其他同service的服务
#修改ribbon的负载均衡策略 服务名 - ribbon - NFLoadBalancerRuleClassName : 策略
service-product:
ribbon:
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
ConnectTimeout: 250 # Ribbon的连接超时时间
ReadTimeout: 1000 # Ribbon的数据读取超时时间
OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
MaxAutoRetries: 1 # 对当前实例的重试次数
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>