小言_互联网的博客

IDEA——Websocket+Springcloud+Eureka+Provider Cluster+Ribbon for neusoft

330人阅读  评论(0)

演示源代码(点击此处下载)

Websocket点对点通信

  • 在进行简单架构后我们开始进行代码编写

  • 配置pom文件
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.webjars/sockjs-client -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>sockjs-client</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.webjars/stomp-websocket -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>stomp-websocket</artifactId>
            <version>2.3.3</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.webjars/jquery -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>jquery</artifactId>
            <version>3.5.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.webjars/webjars-locator-core -->
        <dependency>
            <groupId>org.webjars</groupId>
            <artifactId>webjars-locator-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
  • WebsocketConfig 注册断点
implements WebSocketMessageBrokerConfigurer
  • WebsocketConfig 开启 socketjs 支持
public void registerStompEndpoints(StompEndpointRegistry registry) {
   
        registry.addEndpoint("/chat").setAllowedOriginPatterns("http://localhost:8080").withSockJS();
    }
  • WebsocketConfig 前缀如果是 /topic ,就会把消息转发给消息代理
public void configureMessageBroker(MessageBrokerRegistry registry) {
   
        registry.enableSimpleBroker("/topic","/queue");
    }
  • SecurityConfig写入账户密码
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
   
        auth.inMemoryAuthentication()
                .withUser("admin")
                .password("{noop}admin123")
                .roles("admin")
                .and()
                .withUser("root")
                .password("{noop}123")
                .roles("admin")
                .and()
                .withUser("test")
                .password("{noop}admin123")
                .roles("admin");
    }
  • GreetingController
	@MessageMapping("/hello") // 消息地址
    @SendTo("/topic/greeting") // 转发广播地址,前端监听收到消息
  • GreetingController chat
    principal 用户信息
    param chat 发过来的具体消息
public void chat(Principal principal, Chat chat) {
   
        String name = principal.getName();
        chat.setFrom(name);
        messagingTemplate.convertAndSendToUser(chat.getTo(),"/queue/chat",chat);
    }
  • entity Chat
	private String to;		// 接收方
    private String from;	// 发送方
    private String content;	// 消息内容
    // 展开 getter,setter 方法即可
  • HTML
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/webjars/jquery/jquery.min.js"></script>
    <script src="/webjars/sockjs-client/sockjs.min.js"></script>
    <script src="/webjars/stomp-websocket/stomp.min.js"></script>
</head>
<body>
<div>
    <input id="username" type="text" placeholder="目标用户名">
</div>
<div>
    <input type="text" id="content">
    <button id="send" type="button">发送</button>
</div>
<div id="chat" style="border:5px solid #000"></div>

<script>
    var stompClient;
    $(function () {
    
        connect(); 						// 建立连接
        $('#send').click(function () {
    	// 点击发送
            stompClient.send('/online_chat',{
    },JSON.stringify({
    
                'to':$('#username').val(),
                'content':$('#content').val()
            }))
        })
    })
    
    function connect() {
    							// 建立连接
        var socketjs = new SockJS("/chat");			// 指定端点
        stompClient = Stomp.over(socketjs);			// 操作 websocket
        stompClient.connect({
    },function (frame) {
    	// 建立连接
            stompClient.subscribe('/user/queue/chat',function (greeting) {
    
                var msgBody = JSON.parse(greeting.body);
                $('#chat').append('<div>'+msgBody.from+' : '+ msgBody.content +'</div>')
            })
        })
    }
</script>
</body>
</html>
  • 效果图:

Websocket 一对多通信

  • 消息代理前缀,发送消息的前缀如果是 /topic ,就会把消息转发给消息代理,再把消息广播给所有客户端
	private String name;		// 消息来源
    private String content;		// 消息内容
  • 重写HTML
<script>
        var stompClient;
        $(function () {
   		// 点击连接按钮
            $('#connect').click(function () {
   
                connect();
            })				// 点击断开连接按钮
            $('#disconnect').click(function () {
   
                stompClient.disconnect();
                setConnect(false);
            })				// 点击发送内容按钮
            $('#send').click(function () {
   
                stompClient.send('/hello',{
   },JSON.stringify({
   
                    'name':$('#username').val(),
                    'content':$('#content').val()
                }))
            })
        })
        function connect() {
   
            if (!$('#username').val()) {
   // 判断是否添加用户名
                return;
            }
            var socketjs = new SockJS("/chat");
            stompClient = Stomp.over(socketjs);
            stompClient.connect({
   },function (frame) {
   
                setConnect(true);
                stompClient.subscribe('/topic/greeting',function (greeting) {
    
                    var msgBody = JSON.parse(greeting.body);
                    $('#chat').append('<div>'+msgBody.name+' : '+ msgBody.content +'</div>')
                })
            })
        }
        function setConnect(connected) {
   	// 按钮状态设置
            $('#connect').prop('disabled',connected);
            $('#disconnect').prop('disabled',!connected);
            $('#send').prop('disabled',!connected);
        }
    </script>
  • 效果图:

服务区远程调用

  • 1.创建serviceprovider&consumer (Spring Boot DevTools & Spring Web)
    2.entity 创建 MsgBean
public class MsgBean implements Serializable 
	private Integer id;
    private String content;
    private String statusId;//特征ID
  • 3.controller
@GetMapping("getMsgInfo")
    public MsgBean getMsgInfo(){
   

        MsgBean msgBean =new MsgBean();
        msgBean.setId(1001);
        msgBean.setContent("这里是服务提供方1 创建的msgbean *****从9090端口发出");
        msgBean.setStatusId(UUID.randomUUID().toString());	//随机UUID
        return msgBean;
    }
  • 4.application:9090
    5.consumer MsgService
	//远程调用 9090端口的服务器
    // 需要用到RestTemplate
    //	1.核心配置文件中配置RestTemplate
    //	2. 使用RestTemplate
  • config SpringConfig
	//配置restTemplate
	@Autowired
    RestTemplate restTemplate;

    @Autowired
    DiscoveryClient discoveryClient;

  • 调用9090,返回即可
restTemplate.getForObject("http://127.0.0.1:9090/getMsgInfo",MsgBean.class);
  • controller
@GetMapping("getRemoteMsgByService")
    public MsgBean getRemoteMsgByService(){
   
        MsgBean msg=msgService.getRemoteService();
            return msg;
    }
  • 效果图:



Serviceprovider cluster

  • 1.pom & maven
    2.application Spring名称统一

  • provider

server.port=9090
#spring 应用名称
spring.application.name=serviceprovider-server

#注册eureka客户端
eureka.client.service-url.instance.prefer-ip-address=true
#指定客户端的ip地址
eureka.client.service-url.instance.ip-address=127.0.0.1

eureka.instance.instance-id=serviceprovider-server1-9090

#作为客户端指定注册中心的位置
#eureka.client.service-url.defaultZone=http://127.0.0.1:8891/eureka/
eureka.client.service-url.defaultZone=http://127.0.0.1:8891/eureka/,http://127.0.0.1:8892/eureka/,http://127.0.0.1:8893/eureka/
  • provider2
server.port=9091
#spring 应用名称
spring.application.name=serviceprovider-server

#注册eureka客户端
eureka.client.service-url.instance.prefer-ip-address=true
#指定客户端的ip地址
eureka.client.service-url.instance.ip-address=127.0.0.1

eureka.instance.instance-id=serviceprovider-server1-9091

#作为客户端指定注册中心的位置
#eureka.client.service-url.defaultZone=http://127.0.0.1:8891/eureka/
eureka.client.service-url.defaultZone=http://127.0.0.1:8891/eureka/,http://127.0.0.1:8892/eureka/,http://127.0.0.1:8893/eureka/
  • provider3
server.port=9092
#spring 应用名称
spring.application.name=serviceprovider-server

#注册eureka客户端
eureka.client.service-url.instance.prefer-ip-address=true
#指定客户端的ip地址
eureka.client.service-url.instance.ip-address=127.0.0.1

eureka.instance.instance-id=serviceprovider-server1-9092

#作为客户端指定注册中心的位置
#eureka.client.service-url.defaultZone=http://127.0.0.1:8891/eureka/
eureka.client.service-url.defaultZone=http://127.0.0.1:8891/eureka/,http://127.0.0.1:8892/eureka/,http://127.0.0.1:8893/eureka/
  • 同步controller & entity

  • CTRL C & CTRL V

@RestController
public class HelloController {
   
    @GetMapping("getMsgInfo")
    public MsgBean getMsgInfo(){
   

        MsgBean msgBean =new MsgBean();
        msgBean.setId(181203616);
        msgBean.setContent("这里是服务提供方1 创建的msgbean *****从9090端口发出");
        msgBean.setStatusId(UUID.randomUUID().toString());
        return msgBean;
    }
}
public class MsgBean implements Serializable {
   

    private Integer id;
    private String content;
    private String statusId;

    public Integer getId() {
   
        return id;
    }

    public void setId(Integer id) {
   
        this.id = id;
    }

    public String getContent() {
   
        return content;
    }

    public void setContent(String content) {
   
        this.content = content;
    }

    public String getStatusId() {
   
        return statusId;
    }

    public void setStatusId(String statusId) {
   
        this.statusId = statusId;
    }

    @Override
    public String toString() {
   
        return "MsgBean{" +
                "id=" + id +
                ", content='" + content + '\'' +
                ", statusId='" + statusId + '\'' +
                '}';
    }
}

云端注册中心 SpringCloud-Eureka

  • 1.Spring Boot DevTools & Spring Web & Eureka Server
  • 2.pom & maven
  • 3.port :8891
  • 4.Eureka application
server.port=8891

#spring 名称
spring.application.name = eureka-server-8891

#注册中心配置
# 注册中心主机 ip
eureka.instance.hostname = 127.0.0.1
# 注册自己
eureka.client.register-with-eureka=true
# 检索服务
eureka.client.fetch-registry=true
# 指定当前作为客户端 指定注册中心位置(单机)
#eureka.client.service-url.defaultZone = http://${
   eureka.instance.hostname}:${
   server.port}/eureka
eureka.client.service-url.defaultZone =http://127.0.0.1:8892/eureka/,http://127.0.0.1:8893/eureka/
# 是否关闭自我保护模式(手动关闭)
#eureka.server.enable-self-preservation=false

eureka.instance.instance-id=eureka-server-8891
server.port=8892
spring.application.name=eureka-server:8892

#注册中心配置
# 注册中心主机 ip
eureka.instance.hostname = 127.0.0.1
# 注册自己
eureka.client.register-with-eureka=true
# 检索服务
eureka.client.fetch-registry=true
# 指定当前作为客户端 指定注册中心位置(单机)
#eureka.client.service-url.defaultZone = http://${
   eureka.instance.hostname}:${
   server.port}/eureka
eureka.client.service-url.defaultZone =http://127.0.0.1:8891/eureka/,http://127.0.0.1:8893/eureka/
# 是否关闭自我保护模式(手动关闭)
#eureka.server.enable-self-preservation=false

eureka.instance.instance-id=eureka-server-8892
server.port=8893
spring.application.name=eureka-server:8893

#注册中心配置
# 注册中心主机 ip
eureka.instance.hostname = 127.0.0.1
# 注册自己
eureka.client.register-with-eureka=true
# 检索服务
eureka.client.fetch-registry=true
# 指定当前作为客户端 指定注册中心位置(单机)
#eureka.client.service-url.defaultZone = http://${
   eureka.instance.hostname}:${
   server.port}/eureka
eureka.client.service-url.defaultZone =http://127.0.0.1:8891/eureka/,http://127.0.0.1:8892/eureka/
# 是否关闭自我保护模式(手动关闭)
#eureka.server.enable-self-preservation=false

eureka.instance.instance-id=eureka-server-8893
  • Discovery Client获得服务实例对象,获得其名字
@Autowired
    DiscoveryClient discoveryClient;	//获得注册中心实例对象
    discoveryClient.getInstances("serviceprovider-server");
 MsgBean msgBean = restTemplate.getForObject("http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/getMsgInfo",MsgBean.class);
  • consumer

  • MsgService

public MsgBean getRemoteService(){
   

//        MsgBean msgBean=
//        http://127.0.0.1:9090/getMsgInfo
//        http://127.0.0.1:9091/getMsgInfo
//        http://127.0.0.1:9092/getMsgInfo
//

//        restTemplate.getForObject("http://127.0.0.1:9090/getMsgInfo",MsgBean.class);

//使用DiscoveryClient获得注册中心中 注册的 实例对象
//根据 spring.application.name 去获得实例spring.application.name=serviceprovider-server

      List<ServiceInstance> list = discoveryClient.getInstances("serviceprovider-server");
      //自实现轮询
      //ServiceInstance serviceInstance=list.get((instanceNum++)%3);

      //LoadBalancerClient 自动轮询访问

	ServiceInstance serviceInstance = loadBalancerClient.choose("serviceprovider-server");
	MsgBean msgBean = restTemplate.getForObject("http://"+serviceInstance.getHost()+":"+serviceInstance.getPort()+"/getMsgInfo",MsgBean.class);
        return msgBean;
  • 效果图:


Ribbon实现均衡负载

  • Consumer MsgService中
  • 可获得所有在注册中心的 对应名称的实例数组集合
  • LoadBalancerClient 自动获取对应实例对象
@Autowired
	LoadBalancerClient client;
	LoadBalanLcerClient loadBalancerClient;
	loadBalancerClient.choose("serviceprovider-server");

注解

  • 1.放入configuration配置文件中
  • SpringConfig
	// 配置restTemplate
    @Bean
    @LoadBalanLcer
    public RestTemplate restTemplate(){
   
        return new RestTemplate();
    }
  • MsgService
String url = "http://serviceprovider-server/getMsgInfo";
MsgBean msgBean = restTemplate.getForObject(url,MsgBean.class);

核心配置文件更改均衡算法

  • application
//随机策略
springcloudMovie-Service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
//轮训策略
springcloudMovie-Service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RoundRobinRule
//重试策略
springcloudMovie-Service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RetryRule
//最低并发策略
springcloudMovie-Service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.BestAvailableRule
//可用过滤策略
springcloudMovie-Service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.AvailabilityFilteringRule
//响应时间加权策略
springcloudMovie-Service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.ResponseTimeWeightedRule
  • 效果图:



转载:https://blog.csdn.net/GodOuO/article/details/117077691
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场