文章导航
摘要:由于目前,网上的Spring Cloud的学习的案列
,比较凌乱
而且没有形成整个体系
,因此特开一个专题为跟我学Spring Cloud
,希望帮助到有需要的人
。本文主要介绍如何使用Spring Cloud中的Eureka组件
快速实现微服务的服务注册与发现
。至于安全模式和Eureka Server的HA,后面的文章会详细介绍。如果您觉得,有想了解的内容,参与评论留言。
什么是服务注册与发现
服务注册与发现
在服务化的早期,服务不是很多,服务的注册与发现并不是什么新鲜的名词,Nginx+内部域名服务器方式,甚至Nginx+host文件配置方式也能完成服务的注册与发现。服务上下线需要在nginx,服务器做相应的配置,一旦服务的IP端口发生变化,都需要在nginx上做相应的配置,为了解决这个问题引入服务注册中心。
服务注册,即服务在启动的时候就将服务的IP,端口,版本号等EndPoint注册到注册中心(Eueka,Zookeeper,Consul)对服务进行统一管理.
服务发现,简单的就是说,不管服务上下线,当对某个服务发起请求时,能够快速的从本地缓存或者注册中心的注册列表中,快速找到服务提供者。
服务化早期的做法
示例工程说明
Tips
:代码示例:https://github.com/SoftwareKing/spring-cloud-study/tree/master/sc-eureka-first
Spring MVC中基于无状态的REST
工程可以参考sc-rest-demo下面的sc-rest-provider和sc-rest-consumer,具体使用如下代码所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @RestController @RequestMapping("/sc") public class ConsumerController { @Autowired private RestTemplate restTemplate; @Value("${order.orderServiceUrl}") private String orderServiceUrl; @GetMapping("/consumer/{id}") public OrderModel getOrderInfo(@PathVariable Long id) { return this.restTemplate.getForObject(this.orderServiceUrl + "/sc/order/" + id, OrderModel.class); } }
|
大家注意到没,把http://localhost:8000 ,硬编码到程序中,是不是比较low。可以采用上面代码中的方式:orderServiceUrl解决。但是这样还是比较low,下面介绍一下引入Eureka实现服务注册与发现的处理。
使用Eureka实现服务的注册与发现
搭建注册中心-Eureka Server
1.引入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| <?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.3.RELEASE</version> </parent> <artifactId>sc-eureka-first-server-HA01</artifactId> <name>sc-eureka-first-server-HA01</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka-server</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR5</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
|
- 在Resources目录下创建application.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| server: port: 8761 eureka: client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://localhost:8761/eureka/
|
3.创建Spring Boot主应用程序启动代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package org.xujin.sc.eureka.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; * Eureka Server * @author xujin */ @SpringBootApplication @EnableEurekaServer public class SpringCloudEurekaServer { public static void main(String[] args) { SpringApplication.run(SpringCloudEurekaServer.class, args); } }
|
启动Eureka server测试:
启动sc-eureka-first-server-HA01,访问http://localhost:8761/ ,如下图所示:
创建服务提供者
1.服务提供者,为了演示在这里提供一个简单的订单查询服务
,如工程sc-eureka-first-provider01
和sc-eureka-first-provider02
所示。
2.主程序入口代码,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package org.xujin.sc.eureka.first.order; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; * 服务提供者端,加上@EnableDiscoveryClient注解,完成服务注册。 * @author xujin * @site http://xujin.org */ @SpringBootApplication @EnableDiscoveryClient public class OrderProviderSpringBootAppliaction { public static void main(String[] args) { SpringApplication.run(OrderProviderSpringBootAppliaction.class, args); } }
|
Tips
:如果使用Eureka, 可以使用@EnableEurekaClient注解,但是推荐使用@EnableDiscoveryClient代替@EnableEurekaClient注解,因为@EnableDiscoveryClient是一个高度的抽象, 来自于spring-cloud-commons, 由于Spring Cloud选型是中立的因此抽象出该接口, 当服务注册中心选型改变为Eureka,ZK,Consul时,不需要修改原有代码中的注解。
3.服务提供者暴露的服务-OrderController.java
1 2 3 4 5 6 7 8 9 10 11 12 13
| @RestController public class OrderController { @Autowired private OrderService orderService; @GetMapping("/sc/order/{id}") public OrderModel findOrderById(@PathVariable Long id) { OrderModel orderModel = orderService.findOrderByOrderId(id); return orderModel; } }
|
启动服务提供者,把服务注册信息,注册到Eureka Server注册中心
启动sc-eureka-first-provider01,当启动其中一个服务后刷新Eureka Server会出现安全模式,如下图所示:
启动sc-eureka-first-provider02,刷新Eureka Server如下图所示。
创建服务消费者
服务消费者主要是一个简单的用户服务,用户服务查询订单服务的订单信息。
1.引入相应的依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
| <?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>org.xujin.sc</groupId> <artifactId>sc-eureka-first-consumer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>sc-eureka-first-consumer</name> <url>http://maven.apache.org</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.3.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-eureka</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.16.6</version> <scope>provided</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Camden.SR4</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
|
2.主程序入口代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| package org.xujin.sc.eureka.user; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @EnableDiscoveryClient @SpringBootApplication public class UserConsumerApplication { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } public static void main(String[] args) { SpringApplication.run(UserConsumerApplication.class, args); } }
|
- 消费者调用Controller。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| @RestController public class UserController { private static final Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired private RestTemplate restTemplate; @Autowired private DiscoveryClient discoveryClient; public String serviceUrl() { List<ServiceInstance> list = discoveryClient .getInstances("sc-eureka-first-provider"); if (list != null && list.size() > 0) { return String.valueOf(list.get(0).getUri()); } return null; } @GetMapping("/sc/user/{id}") public Order findByIdByEurekaServer(@PathVariable Long id) { String providerServiceUrl = serviceUrl(); return this.restTemplate.getForObject(providerServiceUrl + "sc/order/" + id, Order.class); } }
|
如上述代码,所示使用discoveryClient.getInstances("sc-eureka-first-provider")
获取服务名为sc-eureka-first-provider
的服务注册列表信息。
测试
先后启动sc-eureka-first-consumer,如没有异常,打开浏览器访问:http://localhost:8010/sc/user/2 ,debug如下所示可以看到
在刷新一下Eureka Server,如图下所示,此时安全模式关闭。
关于安全模式,在本篇文章中,暂不讨论,后面将会专写一篇文章介绍,请暂时忽略。
获取消费者获取服务端消费列表
使用EurekaClient获取服务注册信息
1 2 3 4 5 6 7
| @Autowired private EurekaClient discoveryClient; public String serviceUrl() { InstanceInfo instance = discoveryClient.getNextServerFromEureka("STORES", false); return instance.getHomePageUrl(); }
|
使用DiscoveryClient获取服务注册信息
1 2 3 4 5 6 7 8 9 10
| @Autowired private DiscoveryClient discoveryClient; public String serviceUrl() { List<ServiceInstance> list = discoveryClient.getInstances("STORES"); if (list != null && list.size() > 0 ) { return list.get(0).getUri(); } return null; }
|
参考链接:https://github.com/spring-cloud/spring-cloud-netflix/blob/master/docs/src/main/asciidoc/spring-cloud-netflix.adoc
小结
上面这个例子使用Eureka实现了服务的注册与发现,但是有一个问题就是获取服务注册列表的方式比较low并且太方便,还有一个问题就是没有使用负载均衡(Load Balance),这样就没法实现微服务的HA。在后面的文章将会介绍Eureka Server的HA和使用Robbin实现LB。。
如果您觉得文章不错,可以打赏我喝一杯咖啡!
微信打赏
支付宝打赏