注册中心
Eureka能够自动注册并发现微服务,然后对服务的状态、信息进行集中管理。当我们需要获取其他服务的信息时,只需要向Eureka进行查询。
a: 微服务1 b: 微服务2 c: 微服务3 E: Eureka注册中心 a -> E: 注册 b -> E: 注册 c -> E: 注册
依赖
父项目
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>2024.0 .0 </version> <type>pom</type> <scope>import </scope> </dependency>
Eureka模块
<dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId> </dependency> </dependencies>
配置
eureka: fetch-registry: false registry-with-eureka: false service-url: defaultZone: http://yourhost:port/eureka
@SpringBootApplication @EnableEurekaServer public class EurekaApplication { public static void main (String[] args) { SpringApplication.run(EurekaApplication.class, args); } }
注册服务
首先在需要注册的微服务下导入Eureka依赖:
<dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-netflix-eureka-client</artifactId > </dependency >
然后修改配置appllication.yml
:
spring: application: name: yourservice eureka: client: service-url: defaultZone: http://yourhost:port/eureka
服务发现
注册RestTemplate
@Configuration public class BeanConfiguration { @Bean @LoadBalanced public RestTemplate restTemplate () { return new RestTemplate (); } }
使用spring-application-name代替URL
@Override public UserBorrowDetail getUserBorrowDetailByUid (int uid) { List<Borrow> borrow = borrowMapper.getBorrowByUid(uid); RestTemplate restTemplate = new RestTemplate (); User user = restTemplate.getForObject("http://userservice/user/" +uid, User.class); List<Book> bookList = borrow .stream() .map(b -> restTemplate.getForObject("http://bookservice/book/" +b.getBid(), Book.class)) .collect(Collectors.toList()); return new UserBorrowDetail (user, bookList); }
负载均衡
同一个服务可以注册多个端口,Eureka会为同一服务的多个端口分别进行注册。
使用上面的代码,Eureka会自动地均衡分发请求到不同端口上。
负载均衡保证了服务的安全性,只要不是所有端口的微服务都宕机,Eureka就能够分配请求到可用的端口。
Eureka高可用集群
E: Eureka高可用集群 E: { E1: Eureka服务器1 E2: Eureka服务器2 E3: Eureka服务器3 E1 -> E2 E2 -> E3 E3 -> E1 } a: 微服务1 b: 微服务2 c: 微服务3 a -> E: 注册 b -> E: 注册 c -> E: 注册
编写多个application.yml
server: port: 8801 spring: application: name: eurekaserver eureka: instance: hostname: eureka01 client: fetch-registry: false service-url: defaultZone: http://eureka01:8802/eureka server: port: 8802 spring: application: name: eurekaserver eureka: instance: hostname: eureka02 client: fetch-registry: false service-url: defaultZone: http://eureka01:8801/eureka
微服务写入所有Eureka服务器的地址
eureka: client: service-url: defaultZone: http://localhost:8801/eureka, http://localhost:8802/eureka
LoadBalance 随机分配
默认的LoadBalance是轮询模式,想修改为随机分配,需要修改LoadBalancerConfig
(注意,不需要@Configuration
注解)并在BeanConfiguration
中启用
public class LoadBalancerConfig { @Bean public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer (Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) { String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); return new RandomLoadBalancer (loadBalancerClientFactory.getLazyProvider(name, ServiceInstanceListSupplier.class), name); } } @Configuration @LoadBalancerClient(value = "userservice", configuration = LoadBalancerConfig.class) public class BeanConfiguration { @Bean @LoadBalanced public RestTemplate restTemplate () { return new RestTemplate (); } }
OpenFeign 更方便的HTTP客户端请求工具
OpenFeign和RestTemplate有一样的功能,但是使用起来更加方便
<dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-openfeign</artifactId > </dependency >
使用方法与Mybatis非常类似。
首先,启用OpenFeign
@SpringBootApplication @EnableFeignClients public class SomeApplication { public static void main (String[] args) { SpringApplication.run(SomeApplication.class, args); } }
接下来注册一个interface
@FeignClient("userservice") public interface UserClient { @RequestMapping("/user/{uid}") User getUserById (@PathVariable("uid") int uid) ; }
直接注入使用
@Resource UserClient userClient; @Override public UserBorrowDetail getUserBorrowDetailByUid (int uid) { RestTemplate template = new RestTemplate (); User user = template.getForObject("http://userservice/user/" +uid, User.class); User user = userClient.getUserById(uid); }