Springcloud Eureka详解

1,366 阅读4分钟

Springcloud Eureka详解

Eureka Server 详解

  1. pom依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    
  2. 配置文件

    spring:
      application:
        name: springcloud-demo-eureka-server
    
    
    eureka:
      client:
        # server端也是一个客户端,需要注册到服务端,需要配置服务端的地址
        service-url:
          defaultZone: http://localhost:8762/eureka/
        # 是否需要将该服务注册到服务端,自己就是服务端,不用注册自己
        register-with-eureka: false
        # 是否同步其他server的注册信息,当有多个Eureka Server端时,需要同步信息
        fetch-registry: false
      # 关掉自我保护,由于服务上线率低,会有警告提示,会认为该服务是在线的,即使该服务已经掉线了。
      server:
        enable-self-preservation: false
    server:
      port: 8762
    
  3. 启动类配置注解@EnableEurekaServer

    @SpringBootApplication
    @EnableEurekaServer
    public class EurekaServer {
        public static void main(String[] args) {
            SpringApplication.run(EurekaServer.class, args);
        }
    }
    
    
  4. 访问地址http://localhost:8762,可以看到界面

Euraka Client详解

  1. pom依赖

        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>
    
    • 作为eureka 客户端,依赖spring-cloud-starter-netflix-eureka-client

    • 对外要提供服务,所以要提供spring-boot-starter-web(没有就会报错,无法启动,204)

      2020-04-14 11:30:28.271  INFO 33156 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_SPRINGCLOUD-DEMO-PROVIER/localhost:springcloud-demo-provier:8091 - registration status: 204
      2020-04-14 11:30:28.272  INFO 33156 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_SPRINGCLOUD-DEMO-PROVIER/localhost:springcloud-demo-provier:8091: registering service...
      2020-04-14 11:30:28.277  INFO 33156 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_SPRINGCLOUD-DEMO-PROVIER/localhost:springcloud-demo-provier:8091 - registration status: 204
      2020-04-14 11:30:28.277  INFO 33156 --- [extShutdownHook] com.netflix.discovery.DiscoveryClient    : Unregistering ...
      2020-04-14 11:30:28.283  INFO 33156 --- [extShutdownHook] com.netflix.discovery.DiscoveryClient    : DiscoveryClient_SPRINGCLOUD-DEMO-PROVIER/localhost:springcloud-demo-provier:8091 - deregister  status: 200
    
  2. 配置文件

    spring:
      application:
        name: springcloud-demo-provier
    server:
      port: 8091
    
    
    eureka:
      client:
        # eureka服务端的地址	
        service-url:
          defaultZone: http://localhost:8762/eureka
    
  3. 启动类配置注解@EnableEurekaClient

@SpringBootApplication
@EnableEurekaClient
public class ProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}
  1. 访问地址http://localhost:8762

可以看到用该服务已经注册到eureka服务端

服务间通信

Feign

提供者

  1. pom依赖

    <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  2. 服务对外暴露接口信息

    @FeignClient(value = "springcloud-demo-provier")
    public interface ProviderApiClient {
    
        @GetMapping("/provider/info")
        String info(@RequestParam("msg") String msg);
    
        @PostMapping("/provider/userinfo")
        String userInfo(@RequestBody User user);
    }
    

    其他服务通过注入ProviderApiClient类,调用info方法,从而间接调用对应的接口。

    注意:

    1. @FeignClient value值是该服务的名称
    2. 参数需要用注解标明,@RequestParam/@PathVariable/@RequestHeader等来构造http请求
  3. 接口

    @RestController
    @RequestMapping("/provider")
    public class ProviderController {
    
        @GetMapping("/info")
        public String info(@RequestParam("msg") String msg) {
            return "springcloud-demo-provider info ----- " + msg;
        }
    
    
        @PostMapping("/userinfo")
        public String userInfo(@RequestBody User user) {
            return user.toString();
        }
    }
    

消费者

  1. pom依赖

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    <dependency>
        <groupId>com.wc</groupId>
        <artifactId>springcloud-demo-provider</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <scope>compile</scope>
    </dependency>
    

    依赖openFeign还要依赖FeignClient所在服务的jar.

  2. 启动类需要标注@EnableFeignClients(basePackages = {"com.wc.api"}),basePackages的值是@FeignClient注解的类所在的包名

  3. 接口

    @RestController
    @RequestMapping("/consumer")
    public class ConsumerController {
    
        @Autowired
        private ProviderApiClient providerApiClient;
    
        @GetMapping("/info")
        public String info(@RequestParam("msg") String msg) {
            System.out.println("ConsumerController msg: " + msg);
            return providerApiClient.info(msg);
    
        }
    
    
        @PostMapping("/userinfo")
        public String userInfo(@RequestBody User user) {
            return providerApiClient.userInfo(user);
    
        }
    }
    

    注入服务提供者的接口,调用方法。

参考链接:

  1. blog.csdn.net/russle/arti…

RestTemplate

  1. 配置restTemplate,@LoadBalanced注解是从Ribbon负载均衡器,从所有的目标服务中按照自己配置的规则找到对应的服务。

    @Component
    public class RestTemplateConfig {
    
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    }
    
  2. get请求调用

    @RestController
    @RequestMapping("/consumer")
    public class ConsumerController {
        @Autowired
        private RestTemplate restTemplate;
    
        private static final String URL = "http://SPRINGCLOUD-DEMO-PROVIER";
    
        @GetMapping("/restinfo")
        public String restInfo(@RequestParam("msg") String msg) {
            String url = String.format(URL + "/provider/info?msg=%s", msg);
            return restTemplate.getForObject(url, String.class);
        }
        
        @GetMapping("/restinfo/{id}")
        public String restInfo(@PathVariable("id" Integer id)) {
            return restTemplate.getForObject(URL + "/provider/info/{id}",
                                             String.class,
                                             id);
        }
    }
    
    

    如果传参值在请求路径中,调用这个方法,后面的参数是请求路径中的参数

    T getForObject(String url, Class responseType, Object... uriVariables) throws RestClientException;

  3. post请求

    如果是请求体传参,直接透传,提供者接口也是使用@RequestBody接收

        @PostMapping("/rest-userinfo2")
        public String restUserInfo2(@RequestBody User user) {
    
            return restTemplate.postForObject(URL + "/provider/userinfo", 
                                              user, 
                                              String.class);
    
        }
    

    如果是表单传参,稍微复杂一点,需要设置content-type。

        public String restUserInfo1(User user) {
            HttpHeaders headers = new HttpHeaders();
            //  请勿轻易改变此提交方式,大部分的情况下,提交方式都是表单提交
            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
            
            //  封装参数,千万不要替换为Map与HashMap,否则参数无法传递
            MultiValueMap<String, String> params = 
                new LinkedMultiValueMap<String, String>();
            
            //  也支持中文
            params.add("name", user.getName());
            params.add("age", user.getAge().toString());
            
            HttpEntity<MultiValueMap<String, String>> requestEntity = 
                new HttpEntity<MultiValueMap<String, String>>(params, headers);
            
            //  执行HTTP请求
            return restTemplate.postForObject(URL + "/provider/userinfo", 
                                              requestEntity, 
                                              String.class);
    
        }
    

    自定义MessageConverter,继承MappingJackson2HttpMessageConverter

    public class MyMessageConverter extends MappingJackson2HttpMessageConverter {
        public MyMessageConverter() {
            List<MediaType> list = new ArrayList<>();
            list.add(MediaType.TEXT_PLAIN);
            list.add(MediaType.TEXT_HTML);
            setSupportedMediaTypes(list);
        }
    }
    
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            RestTemplate restTemplate = new RestTemplate();
            restTemplate.getMessageConverters().add(new MyMessageConverter());
            return restTemplate;
        }
    

    RestTemplate中的方法详细参考:

    github.com/vieyahn2017…