编写不易,转载请注明(http://shihlei.iteye.com/blog/2400190)!
一 服务注册与发现
(1)概述
服务调用基本两端:
服务提供者(Service Provider)、服务消费者(Service Client)
调用方式:
(a)简单版:
直接调用
优点:
简单,快速完成
缺点:
服务消费者感知服务端IP、Port,任何这二者修改,都可能引起客户端都需要修改,极端可能需要重新发布上线。
不利于服务HA。
(b)反向代理版:
在中间增加反向代理,服务消费者依赖反向代理服务器,屏蔽服务提供者后端物理架构。
特点:
客户端,服务器端无入侵性
传统反向代理定位HA和负载均衡,不具备自动注册新服务,添加服务新机能力,可以通过扩展反向代理服务器解决。
(c)服务注册中心版:
服务注册到中心中,服务消费者从中心获取服务IP、Port,再进行请求。
特点:
将核心的服务注册发现能力,已独立中间件形式提供。其实和反向代理的解决方案差不多。
(2)服务注册中心定位
解决:
服务物理设备变动(ip,端口变动),造成客户端需要修改的问题。
目前业界大部分使用基于Docker云架构,提供弹性扩展能力,服务提供者IP,Port无法在发布时就给定,引入服务注册中心,可以适应这种变化。
主要提供功能:
1)服务注册发现
2)心跳同步
3)负载均衡
二 服务注册中心:Eureka
(1)概述:
Eureka:Netflix公司开发的服务发现中间件,用于服务的负载均衡和服务故障转移
SpringCloud 集成了EurekaSever,让我们通过简单配置即可启动
git:https://github.com/Netflix/eureka
wiki:https://github.com/Netflix/eureka/wiki
架构:
(2)基于SpringCloud搭建EurekaServer:
搭建过程重用了《 SpringCloud(一): SpringBoot 创建简单的微服务》中的项目,项目环境可点击查看。
第一步:创建项目,添加依赖:见pom
4.0.0 spring-cloud-eureka-server jar spring-cloud-eureka-server Demo project for Spring Boot x.demo.springcloud spring-cloud 1.0-SNAPSHOT ../../pom.xml UTF-8 UTF-8 1.8 org.springframework.cloud spring-cloud-starter-eureka-server org.springframework.boot spring-boot-maven-plugin
第二步:创建SpringCloud启动类,添加@EnableEurekaServer
package x.demo.springcloud.eureka.server; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; @SpringBootApplication @EnableEurekaServer public class SpringCloudEurekaServerApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudEurekaServerApplication.class, args); } }
第三步:配置EurekaServer相关信息:application.yml
spring: profiles: Standalone application: name: eureka-server-standalone server: port: 8761 eureka: # 每个EurekaServer 都包含一个EurekaClient,用于请求其他节同步 client: service-url: defaultZone: http://localhost:8761/eureka # 单机版不注册到Eureka registerWithEureka: false fetchRegistry: false instance: # 指定实例名称,默认:${spring.cloud.client.hostname}:${spring.application.name}:${spring.application.instance_id:${server.port}}} instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
第四步:访问查看是否成功
(3)Eureka Server集群搭建
Eureka Server 集群主要是各个实例通过EurekaClieint 注册到其他实例(对等体Pear)中,保证服务注册表冗余。
注意:由于要操作必须在所有对等体上生效,服务修改才生效,所以有时候会慢。
规划:启动三个实例,互相注册对等体
Peer1:5001
Peer2:5002
Peer3:5003
第一步:项目如上
第二步:修改application.yml指定各个Peer配置,主要是端口及对等体
特别注意:我将多个Profile写在同一个文件中,咋样yml中约定“---”标识一个Profile
--- #HA 版: 通过运行多个实例并请求他们相互注册, 通过defaultZone 注定本实例要注册到哪些其他的节点 spring: profiles: Peer1 application: name: eureka-server server: port: 50001 eureka: client: service-url: defaultZone: http://localhost:50002/eureka/,http://localhost:50003/eureka/ instance: instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}} --- spring: profiles: Peer2 application: name: eureka-server server: port: 50002 eureka: client: serviceUrl: defaultZone: http://localhost:50001/eureka/,http://localhost:50003/eureka/ instance: instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}} --- spring: profiles: Peer3 application: name: eureka-server server: port: 50003 eureka: client: serviceUrl: defaultZone: http://localhost:50001/eureka/,http://localhost:50002/eureka/ instance: instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}}
第三步:配置启动,idea添加启动操作,以Peer1为例,Peer2,Peer3同
注:第一个Peer启动的时候注册对等体报错正常,因为其他对等体还没启动
异常:com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused
第四步:访问页面验证
三 服务提供者,服务消费者集成EurekaClient
重用前面的项目:见《 SpringCloud(一): SpringBoot 创建简单的微服务》,《SpringCloud(二):声明式RestClient—Feign》
1)spring-cloud-microservice:微服务项目,实现获取当前时间服务
2)spring-cloud-webfront:前端项目,根据业务调用各种微服务,这里只是获取时间。
(1)服务提供者
第一步:依赖
4.0.0 spring-cloud-microservice jar spring-cloud-microservice Demo project for Spring Boot x.demo.springcloud spring-cloud 1.0-SNAPSHOT ../../pom.xml UTF-8 UTF-8 1.8 org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-eureka org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-starter-test test org.apache.commons commons-lang3 org.projectlombok lombok org.springframework.boot spring-boot-maven-plugin
第二步:application.yml 配置 EurekaClient,做服务注册
server: port: 10001 # 服务名称 spring: application: name: microservice-time eureka: client: service-url: defaultZone: http://localhost:50001/eureka/,http://localhost:50002/eureka/,http://localhost:50003/eureka/ instance: instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}} prefer-ip-address: true
第三步:启动集成@EnableDiscoveryClient (可以用@EnableEurekaClient 替代)
package x.demo.springcloud.microservice; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class SpringCloudServiceApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudServiceApplication.class, args); } }
第四步:页面查看注册
(2)服务消费者
第一步:依赖
4.0.0 spring-cloud-webfront 0.0.1-SNAPSHOT jar spring-cloud-webfront Demo project for Spring Boot x.demo.springcloud spring-cloud 1.0-SNAPSHOT ../../pom.xml UTF-8 UTF-8 1.8 org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-eureka org.springframework.cloud spring-cloud-starter-feign org.projectlombok lombok true org.springframework.boot spring-boot-maven-plugin
第二步:application.yml 配置 EurekaClient,做服务发现
server: port: 20001 spring: application: name: webfront eureka: client: service-url: defaultZone: http://localhost:50001/eureka/,http://localhost:50002/eureka/,http://localhost:50003/eureka/ instance: instance-id: ${spring.application.name}:${spring.application.instance_id:${server.port}} prefer-ip-address: true
第三步:基于Feign的服务Client
package x.demo.springcloud.webfront.service.impl.feign; import org.springframework.cloud.netflix.feign.FeignClient; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import x.demo.springcloud.webfront.service.impl.ProtocolResult; //name为服务提供者应用名称 @FeignClient(name = "microservice-time") public interface TimeV1MicroServiceDiscoveryClient { @RequestMapping(method = RequestMethod.GET, value = "/time/v1/now", consumes = MediaType.APPLICATION_JSON_VALUE) ProtocolResultnow(@RequestParam(name = "format", required = false) String format); }
第四步:Service,Controller
package x.demo.springcloud.webfront.service; public interface TimeService { /** * 获取当前时间 * @return 当前时间,格式:yyyy-MM-dd HH:mm:ss */ String now(); }
@Service("timeV1FeignImpl") public class TimeV1FeignImpl implements TimeService { @Resource private TimeV1MicroServiceDiscoveryClient timeV1MicroServiceDiscoveryClient; /** * 获取当前时间 * * @return 当前时间,格式:yyyy-MM-dd HH:mm:ss */ @Override public String now() { ProtocolResultresult = timeV1MicroServiceDiscoveryClient.now(null); return result.getBody(); } }
package x.demo.springcloud.webfront.web; import javax.annotation.Resource; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import x.demo.springcloud.webfront.service.TimeService; @RestController @RequestMapping("/time") public class TimeController { @Resource(name = "timeV1FeignImpl") private TimeService timeService; @GetMapping("/now") public String now() { return timeService.now(); } }
第五步:启动集成@EnableDiscoveryClient (可以用@EnableEurekaClient 替代)
package x.demo.springcloud.webfront; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.feign.EnableFeignClients; @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class SpringCloudWebfrontApplication { public static void main(String[] args) { SpringApplication.run(SpringCloudWebfrontApplication.class, args); } }
第六步:验证
四 参考
https://springcloud.cc/spring-cloud-dalston.html