聲明式Web服務客戶端:Feignweb
聲明式:接口聲明、Annotation驅動spring
Web服務:HTTP的方式做爲通信協議api
客戶端:用於服務調用的存根瀏覽器
Feign:原生並非Spring Web MVC的實現,基於JAX-RS(Java REST 規範)實現。Spring Cloud封裝了Feign,使其支持Spring Web MVC。RestTemplate、HttpMessageConverter服務器
RestTemplate以及Spring Web MVC能夠顯式地自定義HTTPMessageConverter實現。app
假設,有一個Java接口PersonService,Feign能夠將其聲明它是一種HTTP方式調用的。dom
註冊中心(Eureka Server):服務發現和註冊ide
應用名稱:spring-cloud-eureka-serverfetch
application.properties:this
spring.application.name=eureka-server
server.port=12345
##\u53D6\u6D88\u670D\u52A1\u5668\u81EA\u6211\u6CE8\u518C
eureka.client.register-with-eureka=false
##\u4E0D\u9700\u8981\u68C0\u7D22\u670D\u52A1
eureka.client.fetch-registry=false
management.endpoints.web.exposure.include=*
Feign聲明接口(契約):定義一種Java強類型接口
模塊:person-api
Person
public class Person {
private Long id ;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
PersonService
@FeignClient(value = "person-service")//服務方應用的名稱
public interface PersonService {
@PostMapping("/person/save")
boolean save(@RequestBody Person person);
@GetMapping("/person/findall")
Collection findAll();
}
Feign客戶(服務消費)端:調用Feign聲明接口
應用名稱:person-client
依賴:person-api
建立客戶端Controller
@RestController
public class PersonServiceController implements PersonService{
private final PersonService personService;
@Autowired
public PersonServiceController(PersonService personService) {
this.personService = personService;
}
@PostMapping("/person/save")//實現了PersonService接口後能夠不用寫mapping地址
@Override
public boolean save(@RequestBody Person person) {
return personService.save(person);
}
@GetMapping("/person/findall")
@Override
public Collection findAll() {
return personService.findAll();
}
}
建立啓動類
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(clients = PersonService.class)
public class FeignClientBootStrapApplication {
public static void main(String[] args) {
SpringApplication.run(FeignClientBootStrapApplication.class, args);
}
}
配置application.properties
spring.application.name=person-client
server.port=8080
management.endpoints.web.exposure.include=*
eureka.client.serviceUrl.defaultZone=http://localhost:12345/eureka
Feign服務(服務提供)端:不必定強制實現Feign聲明接口
應用名稱:person-service
依賴:person-api
建立PersonServiceController
@RestController
public class PersonServiceController implements PersonService{
private final ConcurrentHashMap map = new ConcurrentHashMap();
@PostMapping("/person/save")//實現了PersonService接口後能夠不用寫mapping地址
@Override
public boolean save(@RequestBody Person person) {
return map.put(person.getId(), person) == null;
}
@GetMapping("/person/findall")
@Override
public Collection findAll() {
return map.values();
}
}
建立服務端啓動類
@SpringBootApplication
@EnableEurekaClient
public class FeignServiceBootStrapApplication {
public static void main(String[] args) {
SpringApplication.run(FeignServiceBootStrapApplication.class, args);
}
}
配置application.properties
spring.application.name=person-service
server.port=9090
management.endpoints.web.exposure.include=*
eureka.client.serviceUrl.defaultZone=http://localhost:12345/eureka
Feign客戶(服務消費)端、Feign服務(服務提供)端,以及Feign聲明接口(契約)存放在同一個工程目錄。
調用順序
瀏覽器 ->person-client->person-service
person-api定義了@FeignClients(value="person-service"),person-service實際是一個服務器提供方的應用名稱。
person-client 能夠感知person-service應用存在的,而且Spring Cloud幫助解析PersonService中聲明的應用名稱:
「person-service」,所以person-client在調用PersonService服務時,實際就路由到person-service的URL
整合Netflix Ribbon無錫人流多少錢 http://www.bhnnk120.com/
關閉Eureka註冊
調整person-client關閉Eureka
ribbon.eureka.enabled = false
定義服務ribbon的服務列表(服務名稱:person-service)
person-service.ribbon.listOfServers = http://localhost:9090,http://localhost:9090,http://localhost:9090
徹底取消Eureka註冊
將其註釋掉 //@EnableEurekaClient
自定義Ribbon的規則
接口和Netfilx內部實現
IRule
隨機規則:RandomRule
最可用規則:BestAvailableRule
輪詢規則:RoundRobinRule
重試實現:RetryRule
客戶端配置:ClientConfigEnableRoundRobinRule
可用性過濾規則:AvailabilityFilteringRule
RT權重規則:WeightedResponseTimeRule
規避區域規則:ZoneAvoidanceRule
實現IRule
public class MyRule extends RandomRule{
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
@Override
public Server choose(Object key) {
ILoadBalancer balancer = getLoadBalancer();
List allServers = balancer.getAllServers();
//默認只返回第一個服務
return allServers.get(0);
}
}
暴露自定義實現爲Spring Bean
@Bean
public MyRule myRule() {
return new MyRule();
}
激活配置
@RibbonClient(value = "person-service",configuration = MyRule.class)
驗證結果
[localhost:9090, localhost:9090, localhost:9090]
整合Netflix Hystrix
調整Feign接口
@FeignClient(value = "person-service" ,fallback = PersonServiceFallBack.class)//服務方應用的名稱
public interface PersonService {
@PostMapping("/person/save")
boolean save(@RequestBody Person person);
@GetMapping("/person/findall")
Collection findAll();
}
添加Fallback實現
public class PersonServiceFallBack implements PersonService{
@Override
public boolean save(Person person) {
return false;
}
@Override
public Collection findAll() {
return Collections.emptyList();
}
}
調整客戶端激活Hystrix
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(clients = PersonService.class)
@RibbonClient(value = "person-service",configuration = MyRule.class)
@EnableHystrix
public class FeignClientBootStrapApplication {
public static void main(String[] args) {
SpringApplication.run(FeignClientBootStrapApplication.class, args);
}
@Bean
public MyRule myRule() {
return new MyRule();
}
}